KEY FIX: WebKit's GdkWindow receives all pointer events. Connecting button-press-event on the GtkWindow never fires. Must connect on the WebKitWebView widget itself (the Wails pattern). C library now: - Walks widget tree to find deepest child (WebKitWebView) - Connects button-press + motion-notify on the WebView - Does hit-test in C (8px border zone) - Calls gtk_window_begin_resize_drag with real event data - Returns TRUE to consume border clicks, FALSE for interior |
||
|---|---|---|
| .. | ||
| clients/ts | ||
| native | ||
| src | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
agor-pty — PTY Multiplexer Daemon
Standalone Rust daemon that manages terminal sessions via Unix socket IPC. Portable across Tauri and Electrobun frontends.
Architecture
Frontend (Electrobun/Tauri)
↕ Unix Socket IPC (JSON-framed)
agor-ptyd (Rust daemon)
↕ PTY master FDs
Shell processes (/bin/bash, etc.)
Features
- PTY multiplexing: single daemon manages all terminal sessions
- Session persistence: sessions survive frontend disconnects/restarts
- Multi-client: multiple frontends can connect and subscribe to session output
- Auth: 256-bit token authentication per connection
- Output fanout: PTY output fanned to all subscribed clients (non-blocking)
- Graceful shutdown: SIGTERM/SIGINT cleanup
Usage
# Build
cd agor-pty && cargo build --release
# Run daemon
./target/release/agor-ptyd --verbose
# Custom socket directory
./target/release/agor-ptyd --socket-dir /tmp/agor-test
# Custom default shell
./target/release/agor-ptyd --shell /bin/zsh
IPC Protocol
JSON messages over Unix socket, newline-delimited.
Client → Daemon
Auth { token }— authenticate (must be first message)CreateSession { id, shell, cwd, env, cols, rows }— spawn shellWriteInput { session_id, data }— send input to PTYResize { session_id, cols, rows }— resize terminalSubscribe { session_id }— receive output from sessionUnsubscribe { session_id }— stop receiving outputCloseSession { session_id }— kill sessionListSessions— get all active sessionsPing— keepalive
Daemon → Client
AuthResult { ok }— auth responseSessionCreated { session_id, pid }— session spawnedSessionOutput { session_id, data }— PTY output (base64)SessionClosed { session_id, exit_code }— session endedSessionList { sessions }— list responsePong— keepalive responseError { message }— error
Integration
As library (for Tauri)
use agor_pty::protocol::{ClientMessage, DaemonMessage};
TypeScript client (for Electrobun)
See clients/ts/ for the IPC client module.
Directory Structure
agor-pty/
├── Cargo.toml
├── README.md
├── src/
│ ├── main.rs — daemon entry, CLI, signals
│ ├── lib.rs — library re-exports
│ ├── protocol.rs — IPC message types
│ ├── session.rs — PTY session management
│ ├── daemon.rs — Unix socket server
│ └── auth.rs — token authentication
└── clients/
└── ts/ — TypeScript IPC client (for Electrobun/Bun)