1598 lines
51 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>API Reference - DWN Documentation</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<button class="mobile-menu-btn">Menu</button>
<div class="layout">
<aside class="sidebar">
<div class="sidebar-header">
<h1>DWN</h1>
<span class="version">v2.0.0</span>
</div>
<div class="search-box">
<input type="text" class="search-input" placeholder="Search docs...">
</div>
<nav class="sidebar-nav">
<div class="nav-section">
<div class="nav-section-title">Getting Started</div>
<a href="index.html" class="nav-link">Introduction</a>
<a href="installation.html" class="nav-link">Installation</a>
<a href="quickstart.html" class="nav-link">Quick Start</a>
</div>
<div class="nav-section">
<div class="nav-section-title">User Guide</div>
<a href="features.html" class="nav-link">Features</a>
<a href="shortcuts.html" class="nav-link">Keyboard Shortcuts</a>
<a href="configuration.html" class="nav-link">Configuration</a>
<a href="layouts.html" class="nav-link">Layouts</a>
<a href="ai-features.html" class="nav-link">AI Integration</a>
</div>
<div class="nav-section">
<div class="nav-section-title">API Reference</div>
<a href="api-overview.html" class="nav-link">API Overview</a>
<a href="api-reference.html" class="nav-link active">API Reference</a>
<a href="api-examples.html" class="nav-link">API Examples</a>
</div>
<div class="nav-section">
<div class="nav-section-title">Advanced</div>
<a href="architecture.html" class="nav-link">Architecture</a>
<a href="abstraction-layer.html" class="nav-link">Abstraction Layer</a>
<a href="plugin-development.html" class="nav-link">Plugin Development</a>
<a href="building.html" class="nav-link">Building from Source</a>
</div>
</nav>
</aside>
<main class="main-content">
<div class="content">
<div class="page-header">
<h1>API Reference</h1>
<p class="lead">Complete WebSocket API command reference</p>
</div>
<div class="toc">
<div class="toc-title">On this page</div>
<ul class="toc-list">
<li><a href="#clients">Client Commands</a></li>
<li><a href="#workspaces">Workspace Commands</a></li>
<li><a href="#layout">Layout Commands</a></li>
<li><a href="#keyboard">Keyboard Commands</a></li>
<li><a href="#mouse">Mouse Commands</a></li>
<li><a href="#screenshot">Screenshot Commands</a></li>
<li><a href="#ocr">OCR Commands</a></li>
<li><a href="#notifications">Notification Commands</a></li>
<li><a href="#systray">System Tray Commands</a></li>
<li><a href="#panels">Panel Commands</a></li>
<li><a href="#ai">AI Commands</a></li>
<li><a href="#news">News Commands</a></li>
<li><a href="#demo">Demo/Tutorial Commands</a></li>
<li><a href="#config">Configuration Commands</a></li>
<li><a href="#events">Event Subscription</a></li>
<li><a href="#system">System Commands</a></li>
</ul>
</div>
<h2 id="clients">Client Commands</h2>
<h3>get_clients</h3>
<p>Get list of all managed clients (windows).</p>
<div class="code-block">
<pre><code>// Request
{"command": "get_clients"}
// Response
{
"status": "ok",
"clients": [
{
"window": 12345678,
"title": "Window Title",
"class": "window-class",
"workspace": 0,
"x": 0,
"y": 32,
"width": 960,
"height": 540,
"focused": true,
"floating": false,
"fullscreen": false,
"maximized": false,
"minimized": false
}
]
}</code></pre>
</div>
<h3>find_clients</h3>
<p>Search for clients by title, class, or workspace.</p>
<div class="code-block">
<pre><code>// Request - find by title (substring match)
{"command": "find_clients", "title": "Firefox"}
// Request - find by class
{"command": "find_clients", "class": "terminal"}
// Request - find by workspace
{"command": "find_clients", "workspace": 2}
// Request - combine filters
{"command": "find_clients", "class": "code", "workspace": 0}
// Response
{
"status": "ok",
"clients": [...]
}</code></pre>
</div>
<h3>get_focused_client</h3>
<p>Get the currently focused client.</p>
<div class="code-block">
<pre><code>// Request
{"command": "get_focused_client"}
// Response
{
"status": "ok",
"client": {
"window": 12345678,
"title": "...",
"class": "...",
...
}
}</code></pre>
</div>
<h3>focus_client</h3>
<p>Focus a client by window ID. Switches workspace if needed.</p>
<div class="code-block">
<pre><code>// Request
{"command": "focus_client", "window": 12345678}
// Response (returns current status)
{
"status": "ok",
"version": "2.0.0",
"current_workspace": 0,
"client_count": 5
}</code></pre>
</div>
<h3>close_client</h3>
<p>Close a client gracefully (sends WM_DELETE_WINDOW).</p>
<div class="code-block">
<pre><code>// Request
{"command": "close_client", "window": 12345678}
// Response
{"status": "ok"}</code></pre>
</div>
<h3>kill_client</h3>
<p>Force kill a client (XKillClient). Use when close_client fails.</p>
<div class="code-block">
<pre><code>// Request
{"command": "kill_client", "window": 12345678}
// Response
{"status": "ok"}</code></pre>
</div>
<h3>move_client</h3>
<p>Move a client to specified position.</p>
<div class="code-block">
<pre><code>// Request
{
"command": "move_client",
"window": 12345678,
"x": 100,
"y": 100
}
// Response
{"status": "ok"}</code></pre>
</div>
<h3>resize_client</h3>
<p>Resize a client to specified dimensions.</p>
<div class="code-block">
<pre><code>// Request
{
"command": "resize_client",
"window": 12345678,
"width": 800,
"height": 600
}
// Response
{"status": "ok"}</code></pre>
</div>
<h3>minimize_client</h3>
<p>Minimize a client.</p>
<div class="code-block">
<pre><code>{"command": "minimize_client", "window": 12345678}</code></pre>
</div>
<h3>restore_client</h3>
<p>Restore a minimized client.</p>
<div class="code-block">
<pre><code>{"command": "restore_client", "window": 12345678}</code></pre>
</div>
<h3>maximize_client</h3>
<p>Maximize or unmaximize a client. Toggles if state not specified.</p>
<div class="code-block">
<pre><code>// Toggle maximize
{"command": "maximize_client", "window": 12345678}
// Set explicit state
{"command": "maximize_client", "window": 12345678, "state": true}</code></pre>
</div>
<h3>fullscreen_client</h3>
<p>Set client fullscreen state. Toggles if state not specified.</p>
<div class="code-block">
<pre><code>// Toggle fullscreen
{"command": "fullscreen_client", "window": 12345678}
// Set explicit state
{"command": "fullscreen_client", "window": 12345678, "state": true}</code></pre>
</div>
<h3>float_client</h3>
<p>Set client floating state. Toggles if state not specified.</p>
<div class="code-block">
<pre><code>// Toggle floating
{"command": "float_client", "window": 12345678}
// Set explicit state
{"command": "float_client", "window": 12345678, "state": true}</code></pre>
</div>
<h3>raise_client</h3>
<p>Raise client to top of stack.</p>
<div class="code-block">
<pre><code>{"command": "raise_client", "window": 12345678}</code></pre>
</div>
<h3>lower_client</h3>
<p>Lower client to bottom of stack.</p>
<div class="code-block">
<pre><code>{"command": "lower_client", "window": 12345678}</code></pre>
</div>
<h2 id="workspaces">Workspace Commands</h2>
<h3>get_workspaces</h3>
<p>Get list of all workspaces.</p>
<div class="code-block">
<pre><code>// Request
{"command": "get_workspaces"}
// Response
{
"status": "ok",
"workspaces": [
{
"id": 0,
"name": "1",
"layout": 0,
"client_count": 3
},
{
"id": 1,
"name": "2",
"layout": 0,
"client_count": 0
}
// ... workspaces 2-8
]
}</code></pre>
</div>
<h3>switch_workspace</h3>
<p>Switch to specified workspace (0-8). Returns current status.</p>
<div class="code-block">
<pre><code>// Request
{"command": "switch_workspace", "workspace": 2}
// Response
{
"status": "ok",
"version": "2.0.0",
"current_workspace": 2,
"client_count": 5
}</code></pre>
</div>
<h3>move_client_to_workspace</h3>
<p>Move specific client to workspace.</p>
<div class="code-block">
<pre><code>{
"command": "move_client_to_workspace",
"window": 12345678,
"workspace": 3
}</code></pre>
</div>
<h3>switch_workspace_next</h3>
<p>Switch to the next workspace (wraps around).</p>
<div class="code-block">
<pre><code>{"command": "switch_workspace_next"}
// Response
{
"status": "ok",
"workspace": 1,
"workspace_name": "2"
}</code></pre>
</div>
<h3>switch_workspace_prev</h3>
<p>Switch to the previous workspace (wraps around).</p>
<div class="code-block">
<pre><code>{"command": "switch_workspace_prev"}</code></pre>
</div>
<h2 id="layout">Layout Commands</h2>
<h3>set_layout</h3>
<p>Set workspace layout mode. Can use string names or numeric values.</p>
<div class="code-block">
<pre><code>// Set layout by name ("tiling", "floating", or "monocle")
{"command": "set_layout", "layout": "floating"}
// Set layout by number (0=tiling, 1=floating, 2=monocle)
{"command": "set_layout", "layout": 1}
// Optionally specify workspace (defaults to current)
{"command": "set_layout", "layout": "monocle", "workspace": 2}</code></pre>
</div>
<h3>cycle_layout</h3>
<p>Cycle to next layout mode (tiling → floating → monocle → tiling).</p>
<div class="code-block">
<pre><code>// Cycle current workspace
{"command": "cycle_layout"}
// Cycle specific workspace
{"command": "cycle_layout", "workspace": 3}</code></pre>
</div>
<h3>set_master_ratio</h3>
<p>Set the master area ratio (0.1-0.9) for tiling layout.</p>
<div class="code-block">
<pre><code>// Set on current workspace
{"command": "set_master_ratio", "ratio": 0.6}
// Set on specific workspace
{"command": "set_master_ratio", "ratio": 0.55, "workspace": 2}
// Response
{
"status": "ok",
"workspace": 0,
"master_ratio": 0.6
}</code></pre>
</div>
<h3>adjust_master_ratio</h3>
<p>Adjust the master area ratio by a delta value.</p>
<div class="code-block">
<pre><code>// Increase master area by 5%
{"command": "adjust_master_ratio", "delta": 0.05}
// Decrease master area by 5%
{"command": "adjust_master_ratio", "delta": -0.05}</code></pre>
</div>
<h3>set_master_count</h3>
<p>Set the number of windows in the master area (1-10).</p>
<div class="code-block">
<pre><code>{"command": "set_master_count", "count": 2}
// Response
{
"status": "ok",
"workspace": 0,
"master_count": 2
}</code></pre>
</div>
<h3>adjust_master_count</h3>
<p>Adjust the master count by a delta value.</p>
<div class="code-block">
<pre><code>// Add one window to master
{"command": "adjust_master_count", "delta": 1}
// Remove one window from master
{"command": "adjust_master_count", "delta": -1}</code></pre>
</div>
<h3>focus_next</h3>
<p>Focus the next window in the current workspace.</p>
<div class="code-block">
<pre><code>{"command": "focus_next"}
// Response
{
"status": "ok",
"focused_window": 12345678,
"focused_title": "Firefox"
}</code></pre>
</div>
<h3>focus_prev</h3>
<p>Focus the previous window in the current workspace.</p>
<div class="code-block">
<pre><code>{"command": "focus_prev"}</code></pre>
</div>
<h3>focus_master</h3>
<p>Focus the first window in the master area.</p>
<div class="code-block">
<pre><code>{"command": "focus_master"}</code></pre>
</div>
<h3>snap_client</h3>
<p>Snap a window to screen edge or corner.</p>
<div class="code-block">
<pre><code>// Snap focused window left
{"command": "snap_client", "direction": "left"}
// Snap specific window
{"command": "snap_client", "window": 12345678, "direction": "right"}
// Directions: left, right, up, down
// Snapping is composable: left then up = top-left corner
// Response
{
"status": "ok",
"window": 12345678,
"snap": {
"horizontal": 1,
"vertical": 0
}
}</code></pre>
</div>
<h2 id="keyboard">Keyboard Commands</h2>
<h3>key_press</h3>
<p>Simulate key press (key down only). Use <code>keysym</code> (X11 keysym name) or <code>keycode</code>.</p>
<div class="code-block">
<pre><code>// By keysym name (X11 keysym names)
{"command": "key_press", "keysym": "a"}
{"command": "key_press", "keysym": "Return"}
{"command": "key_press", "keysym": "Tab"}
{"command": "key_press", "keysym": "Escape"}
{"command": "key_press", "keysym": "F1"}
{"command": "key_press", "keysym": "Control_L"}
// By keycode (hardware keycode)
{"command": "key_press", "keycode": 38}</code></pre>
</div>
<h3>key_release</h3>
<p>Simulate key release (key up only).</p>
<div class="code-block">
<pre><code>{"command": "key_release", "keysym": "a"}
{"command": "key_release", "keycode": 38}</code></pre>
</div>
<h3>key_tap</h3>
<p>Simulate a complete keypress (press + release) with optional modifiers.</p>
<div class="code-block">
<pre><code>// Simple key tap
{"command": "key_tap", "keysym": "a"}
// With modifiers (modifier keysym names)
{"command": "key_tap", "keysym": "c", "modifiers": ["Control_L"]}
{"command": "key_tap", "keysym": "t", "modifiers": ["Control_L", "Alt_L"]}
{"command": "key_tap", "keysym": "s", "modifiers": ["Control_L", "Shift_L"]}
// Special keys
{"command": "key_tap", "keysym": "Return"}
{"command": "key_tap", "keysym": "Tab"}
{"command": "key_tap", "keysym": "Escape"}
{"command": "key_tap", "keysym": "F1"}</code></pre>
</div>
<p>Common modifier keysyms: <code>Control_L</code>, <code>Control_R</code>, <code>Shift_L</code>, <code>Shift_R</code>, <code>Alt_L</code>, <code>Alt_R</code>, <code>Super_L</code>, <code>Super_R</code></p>
<h3>key_type</h3>
<p>Type a string of text. Automatically handles shift for uppercase and special characters.</p>
<div class="code-block">
<pre><code>{"command": "key_type", "text": "Hello, World!"}</code></pre>
</div>
<h2 id="mouse">Mouse Commands</h2>
<h3>mouse_move</h3>
<p>Move mouse to absolute position.</p>
<div class="code-block">
<pre><code>{"command": "mouse_move", "x": 500, "y": 300}</code></pre>
</div>
<h3>mouse_move_relative</h3>
<p>Move mouse relative to current position.</p>
<div class="code-block">
<pre><code>{"command": "mouse_move_relative", "dx": 10, "dy": -5}</code></pre>
</div>
<h3>mouse_click</h3>
<p>Click mouse button (press + release).</p>
<div class="code-block">
<pre><code>// Left click at current position
{"command": "mouse_click", "button": 1}
// Right click at specific position (moves mouse first)
{"command": "mouse_click", "button": 3, "x": 100, "y": 200}</code></pre>
</div>
<p>Buttons: 1=left, 2=middle, 3=right, 4=scroll up, 5=scroll down</p>
<h3>mouse_press</h3>
<p>Press mouse button without releasing (for drag operations).</p>
<div class="code-block">
<pre><code>{"command": "mouse_press", "button": 1}</code></pre>
</div>
<h3>mouse_release</h3>
<p>Release mouse button.</p>
<div class="code-block">
<pre><code>{"command": "mouse_release", "button": 1}</code></pre>
</div>
<h3>mouse_scroll</h3>
<p>Scroll mouse wheel.</p>
<div class="code-block">
<pre><code>// Scroll up (amount 1-100, default 1)
{"command": "mouse_scroll", "direction": "up", "amount": 3}
// Scroll down
{"command": "mouse_scroll", "direction": "down", "amount": 3}</code></pre>
</div>
<h3>get_mouse_position</h3>
<p>Get current mouse position and window under cursor.</p>
<div class="code-block">
<pre><code>// Request
{"command": "get_mouse_position"}
// Response
{
"status": "ok",
"x": 500,
"y": 300,
"window_x": 100,
"window_y": 50,
"window": 12345678
}</code></pre>
</div>
<h2 id="screenshot">Screenshot Commands</h2>
<h3>screenshot</h3>
<p>Capture screenshot. Returns base64-encoded PNG.</p>
<h4>Async Mode (Default)</h4>
<p>By default, screenshot operations run asynchronously to avoid blocking the API. Set <code>"async": false</code> for synchronous behavior.</p>
<div class="code-block">
<pre><code>// Async (default) - returns when capture completes
{"command": "screenshot", "mode": "fullscreen"}
// Synchronous - blocks until complete
{"command": "screenshot", "mode": "fullscreen", "async": false}</code></pre>
</div>
<h4>Fullscreen Mode</h4>
<div class="code-block">
<pre><code>// Request
{"command": "screenshot", "mode": "fullscreen"}
// Response
{
"status": "ok",
"format": "png",
"encoding": "base64",
"width": 1920,
"height": 1080,
"data": "iVBORw0KGgoAAAANSUhEUg..."
}</code></pre>
</div>
<h4>Active Window Mode</h4>
<div class="code-block">
<pre><code>{"command": "screenshot", "mode": "active"}</code></pre>
</div>
<h4>Specific Window Mode</h4>
<div class="code-block">
<pre><code>{"command": "screenshot", "mode": "window", "window": 12345678}</code></pre>
</div>
<h4>Area Mode</h4>
<div class="code-block">
<pre><code>{
"command": "screenshot",
"mode": "area",
"x": 100,
"y": 100,
"width": 400,
"height": 300
}</code></pre>
</div>
<h2 id="ocr">OCR Commands</h2>
<h3>ocr</h3>
<p>Extract text from image using OCR.</p>
<h4>Async Mode (Default)</h4>
<p>OCR operations run asynchronously by default since text extraction can take 1-10 seconds. Set <code>"async": false</code> for synchronous behavior.</p>
<div class="code-block">
<pre><code>// Async (default)
{"command": "ocr", "image": "...", "language": "eng"}
// Synchronous
{"command": "ocr", "image": "...", "language": "eng", "async": false}</code></pre>
</div>
<h4>Request/Response</h4>
<div class="code-block">
<pre><code>// Request
{
"command": "ocr",
"image": "iVBORw0KGgoAAAANSUhEUg...", // base64 PNG
"language": "eng" // optional, default "eng"
}
// Response
{
"status": "ok",
"text": "Extracted text from image...",
"confidence": 0.95
}</code></pre>
</div>
<p>Common language codes: <code>eng</code> (English), <code>deu</code> (German), <code>fra</code> (French), <code>spa</code> (Spanish)</p>
<h2 id="notifications">Notification Commands</h2>
<h3>notify</h3>
<p>Show a desktop notification.</p>
<div class="code-block">
<pre><code>// Request
{
"command": "notify",
"summary": "Hello!",
"body": "This is a notification message",
"app_name": "My App",
"timeout": 5000
}
// Response
{
"status": "ok",
"notification_id": 1
}</code></pre>
</div>
<h3>close_notification</h3>
<p>Close a notification by ID.</p>
<div class="code-block">
<pre><code>{"command": "close_notification", "id": 1}</code></pre>
</div>
<h3>get_notifications</h3>
<p>Get list of active notifications.</p>
<div class="code-block">
<pre><code>{"command": "get_notifications"}
// Response
{
"status": "ok",
"notifications": [
{
"id": 1,
"app_name": "My App",
"summary": "Hello!",
"body": "This is a notification",
"timeout": 5000,
"urgency": 1
}
]
}</code></pre>
</div>
<h2 id="systray">System Tray Commands</h2>
<h3>get_battery_state</h3>
<p>Get battery status information.</p>
<div class="code-block">
<pre><code>{"command": "get_battery_state"}
// Response
{
"status": "ok",
"battery": {
"present": true,
"charging": false,
"percentage": 75,
"time_remaining": 180
}
}</code></pre>
</div>
<h3>get_audio_state</h3>
<p>Get audio volume and mute status.</p>
<div class="code-block">
<pre><code>{"command": "get_audio_state"}
// Response
{
"status": "ok",
"volume": 50,
"muted": false
}</code></pre>
</div>
<h3>set_audio_volume</h3>
<p>Set audio volume (0-100).</p>
<div class="code-block">
<pre><code>{"command": "set_audio_volume", "volume": 75}
// Response
{
"status": "ok",
"volume": 75,
"muted": false
}</code></pre>
</div>
<h3>toggle_audio_mute</h3>
<p>Toggle audio mute state.</p>
<div class="code-block">
<pre><code>{"command": "toggle_audio_mute"}
// Response
{
"status": "ok",
"muted": true,
"volume": 75
}</code></pre>
</div>
<h3>get_wifi_state</h3>
<p>Get WiFi connection status.</p>
<div class="code-block">
<pre><code>{"command": "get_wifi_state"}
// Response
{
"status": "ok",
"enabled": true,
"connected": true,
"ssid": "MyNetwork",
"signal_strength": 80
}</code></pre>
</div>
<h2 id="panels">Panel Commands</h2>
<h3>get_panel_state</h3>
<p>Get state of top and bottom panels.</p>
<div class="code-block">
<pre><code>{"command": "get_panel_state"}
// Response
{
"status": "ok",
"top_panel": {
"enabled": true,
"visible": true,
"x": 0,
"y": 0,
"width": 1920,
"height": 32
},
"bottom_panel": {
"enabled": true,
"visible": true,
"x": 0,
"y": 1048,
"width": 1920,
"height": 32
}
}</code></pre>
</div>
<h3>show_panel</h3>
<p>Show a panel.</p>
<div class="code-block">
<pre><code>{"command": "show_panel", "panel": "top"}
{"command": "show_panel", "panel": "bottom"}</code></pre>
</div>
<h3>hide_panel</h3>
<p>Hide a panel.</p>
<div class="code-block">
<pre><code>{"command": "hide_panel", "panel": "top"}</code></pre>
</div>
<h3>toggle_panel</h3>
<p>Toggle panel visibility.</p>
<div class="code-block">
<pre><code>{"command": "toggle_panel", "panel": "bottom"}</code></pre>
</div>
<h2 id="ai">AI Commands</h2>
<h3>ai_is_available</h3>
<p>Check if AI features are available (API key configured).</p>
<div class="code-block">
<pre><code>{"command": "ai_is_available"}
// Response
{
"status": "ok",
"available": true,
"model": "google/gemini-2.0-flash-exp:free"
}</code></pre>
</div>
<h3>ai_command</h3>
<p>Send a command to the AI assistant. Async by default.</p>
<div class="code-block">
<pre><code>// Request
{
"command": "ai_command",
"prompt": "What windows are open?",
"async": true
}
// Response (when complete)
{
"status": "ok",
"response": "You have 3 windows open: Firefox, Terminal, and VS Code..."
}</code></pre>
</div>
<h3>exa_is_available</h3>
<p>Check if Exa semantic search is available.</p>
<div class="code-block">
<pre><code>{"command": "exa_is_available"}
// Response
{
"status": "ok",
"available": true
}</code></pre>
</div>
<h3>exa_search</h3>
<p>Perform semantic web search using Exa. Async by default.</p>
<div class="code-block">
<pre><code>// Request
{
"command": "exa_search",
"query": "how to configure nginx reverse proxy",
"async": true
}
// Response
{
"status": "ok",
"results": [
{
"title": "NGINX Reverse Proxy Configuration",
"url": "https://example.com/nginx-guide",
"snippet": "Learn how to configure NGINX as a reverse proxy...",
"score": 0.95
}
]
}</code></pre>
</div>
<h2 id="news">News Commands</h2>
<h3>get_news</h3>
<p>Get news articles from the news ticker.</p>
<div class="code-block">
<pre><code>{"command": "get_news"}
// Response
{
"status": "ok",
"current_article": 0,
"article_count": 10,
"fetching": false,
"has_error": false,
"articles": [
{
"title": "Breaking News...",
"content": "Article content...",
"link": "https://example.com/news/1",
"author": "John Doe",
"sentiment": 0,
"sentiment_score": 0.5
}
]
}</code></pre>
</div>
<h3>news_next</h3>
<p>Navigate to next news article.</p>
<div class="code-block">
<pre><code>{"command": "news_next"}
// Response
{
"status": "ok",
"current_article": 1,
"title": "Next article title..."
}</code></pre>
</div>
<h3>news_prev</h3>
<p>Navigate to previous news article.</p>
<div class="code-block">
<pre><code>{"command": "news_prev"}</code></pre>
</div>
<h3>news_open</h3>
<p>Open current news article in browser.</p>
<div class="code-block">
<pre><code>{"command": "news_open"}
// Response
{
"status": "ok",
"link": "https://example.com/news/1"
}</code></pre>
</div>
<h2 id="demo">Demo/Tutorial Commands</h2>
<h3>start_demo</h3>
<p>Start the automated demo mode.</p>
<div class="code-block">
<pre><code>{"command": "start_demo"}</code></pre>
</div>
<h3>stop_demo</h3>
<p>Stop the demo mode.</p>
<div class="code-block">
<pre><code>{"command": "stop_demo"}</code></pre>
</div>
<h3>get_demo_state</h3>
<p>Get current demo mode state.</p>
<div class="code-block">
<pre><code>{"command": "get_demo_state"}
// Response
{
"status": "ok",
"active": true,
"phase": 2,
"phase_name": "DEMO_WORKSPACES",
"step": 3
}</code></pre>
</div>
<h3>start_tutorial</h3>
<p>Start the interactive tutorial.</p>
<div class="code-block">
<pre><code>{"command": "start_tutorial"}</code></pre>
</div>
<h3>stop_tutorial</h3>
<p>Stop the tutorial.</p>
<div class="code-block">
<pre><code>{"command": "stop_tutorial"}</code></pre>
</div>
<h3>get_tutorial_state</h3>
<p>Get current tutorial state.</p>
<div class="code-block">
<pre><code>{"command": "get_tutorial_state"}
// Response
{
"status": "ok",
"active": true
}</code></pre>
</div>
<h2 id="config">Configuration Commands</h2>
<h3>get_config</h3>
<p>Get configuration values. Get a specific key or all config.</p>
<div class="code-block">
<pre><code>// Get specific key
{"command": "get_config", "key": "terminal"}
// Response
{
"status": "ok",
"value": "xfce4-terminal"
}
// Get all config
{"command": "get_config"}
// Response
{
"status": "ok",
"config": {
"terminal": "xfce4-terminal",
"launcher": "dmenu_run",
"focus_mode": "click",
"border_width": 0,
"panel_height": 32,
"gap": 0,
"ai_enabled": true,
"fade_speed": 0.5,
"fade_intensity": 1.0
...
}
}</code></pre>
</div>
<h3>reload_config</h3>
<p>Reload configuration from file.</p>
<div class="code-block">
<pre><code>{"command": "reload_config"}
// Response
{
"status": "ok"
}</code></pre>
</div>
<h3>get_keybindings</h3>
<p>Get list of all keyboard shortcuts.</p>
<div class="code-block">
<pre><code>{"command": "get_keybindings"}
// Response
{
"status": "ok",
"keybindings": [
{
"key": "t",
"modifiers": "ctrl+alt",
"description": "Open terminal"
},
{
"key": "F4",
"modifiers": "alt",
"description": "Close focused window"
}
...
]
}</code></pre>
</div>
<h2 id="events">Event Subscription</h2>
<p>DWN supports real-time event streaming over WebSocket. Subscribe to events to receive notifications about window actions, workspace changes, input events, and more.</p>
<h3>list_events</h3>
<p>Get list of all available event types.</p>
<div class="code-block">
<pre><code>// Request
{"command": "list_events"}
// Response
{
"status": "ok",
"events": [
"window_created",
"window_destroyed",
"window_focused",
"window_unfocused",
"window_moved",
"window_resized",
"window_minimized",
"window_restored",
"window_maximized",
"window_unmaximized",
"window_fullscreen",
"window_unfullscreen",
"window_floating",
"window_unfloating",
"window_title_changed",
"window_raised",
"window_lowered",
"workspace_switched",
"workspace_window_added",
"workspace_window_removed",
"workspace_layout_changed",
"workspace_master_ratio_changed",
"workspace_master_count_changed",
"workspace_arranged",
"layout_changed",
"key_pressed",
"key_released",
"shortcut_triggered",
"mouse_moved",
"mouse_button_pressed",
"mouse_button_released",
"drag_started",
"drag_ended",
"show_desktop_toggled",
"notification_shown",
"notification_closed"
]
}</code></pre>
</div>
<h3>subscribe</h3>
<p>Subscribe to specific events or all events.</p>
<div class="code-block">
<pre><code>// Subscribe to specific events
{"command": "subscribe", "events": ["window_focused", "window_created"]}
// Subscribe to all events
{"command": "subscribe", "all": true}
// Response
{
"status": "ok",
"subscribed": ["window_focused", "window_created"]
}</code></pre>
</div>
<h3>unsubscribe</h3>
<p>Unsubscribe from specific events or all events.</p>
<div class="code-block">
<pre><code>// Unsubscribe from specific events
{"command": "unsubscribe", "events": ["window_focused"]}
// Unsubscribe from all events
{"command": "unsubscribe", "all": true}
// Response
{"status": "ok"}</code></pre>
</div>
<h3>Event Message Format</h3>
<p>When subscribed, events are pushed to the client as JSON messages:</p>
<div class="code-block">
<pre><code>// Window focus event
{
"type": "event",
"event": "window_focused",
"data": {
"window": 12345678,
"title": "Firefox",
"previous_window": 87654321
}
}
// Window moved event
{
"type": "event",
"event": "window_moved",
"data": {
"window": 12345678,
"old_x": 0,
"old_y": 32,
"new_x": 100,
"new_y": 100
}
}
// Workspace switched event
{
"type": "event",
"event": "workspace_switched",
"data": {
"old_workspace": 0,
"new_workspace": 2
}
}
// Keyboard shortcut triggered
{
"type": "event",
"event": "shortcut_triggered",
"data": {
"name": "Return",
"description": "Open terminal"
}
}
// Notification shown
{
"type": "event",
"event": "notification_shown",
"data": {
"id": 1,
"summary": "New Message",
"body": "You have a new message"
}
}
// Fade speed changed
{
"type": "event",
"event": "fade_speed_changed",
"data": {
"old_speed": 0.5,
"new_speed": 1.0
}
}
// Fade intensity changed
{
"type": "event",
"event": "fade_intensity_changed",
"data": {
"old_intensity": 1.0,
"new_intensity": 0.8
}
}</code></pre>
</div>
<h3>Event Types Reference</h3>
<div class="table-container">
<table>
<thead>
<tr>
<th>Event</th>
<th>Description</th>
<th>Data Fields</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>window_created</code></td>
<td>New window managed</td>
<td>window, title, class, workspace</td>
</tr>
<tr>
<td><code>window_destroyed</code></td>
<td>Window closed</td>
<td>window, title, workspace</td>
</tr>
<tr>
<td><code>window_focused</code></td>
<td>Window received focus</td>
<td>window, title, previous_window</td>
</tr>
<tr>
<td><code>window_unfocused</code></td>
<td>Window lost focus</td>
<td>window, title</td>
</tr>
<tr>
<td><code>window_moved</code></td>
<td>Window position changed</td>
<td>window, old_x, old_y, new_x, new_y</td>
</tr>
<tr>
<td><code>window_resized</code></td>
<td>Window size changed</td>
<td>window, old_width, old_height, new_width, new_height</td>
</tr>
<tr>
<td><code>window_minimized</code></td>
<td>Window minimized</td>
<td>window</td>
</tr>
<tr>
<td><code>window_restored</code></td>
<td>Window restored from minimized</td>
<td>window</td>
</tr>
<tr>
<td><code>window_maximized</code></td>
<td>Window maximized/unmaximized</td>
<td>window, maximized</td>
</tr>
<tr>
<td><code>window_fullscreen</code></td>
<td>Fullscreen toggled</td>
<td>window, fullscreen</td>
</tr>
<tr>
<td><code>window_floating</code></td>
<td>Floating mode toggled</td>
<td>window, floating</td>
</tr>
<tr>
<td><code>window_title_changed</code></td>
<td>Window title updated</td>
<td>window, old_title, new_title</td>
</tr>
<tr>
<td><code>workspace_switched</code></td>
<td>Active workspace changed</td>
<td>old_workspace, new_workspace</td>
</tr>
<tr>
<td><code>workspace_layout_changed</code></td>
<td>Workspace layout changed</td>
<td>workspace, old_layout, new_layout</td>
</tr>
<tr>
<td><code>key_pressed</code></td>
<td>Key pressed</td>
<td>keycode, keysym, modifiers</td>
</tr>
<tr>
<td><code>shortcut_triggered</code></td>
<td>Keyboard shortcut executed</td>
<td>name, description</td>
</tr>
<tr>
<td><code>mouse_button_pressed</code></td>
<td>Mouse button pressed</td>
<td>button, x, y</td>
</tr>
<tr>
<td><code>drag_started</code></td>
<td>Window drag/resize started</td>
<td>window, is_resize</td>
</tr>
<tr>
<td><code>drag_ended</code></td>
<td>Window drag/resize ended</td>
<td>window, is_resize</td>
</tr>
<tr>
<td><code>show_desktop_toggled</code></td>
<td>Show desktop mode toggled</td>
<td>shown</td>
</tr>
<tr>
<td><code>notification_shown</code></td>
<td>Notification displayed</td>
<td>id, summary, body</td>
</tr>
<tr>
<td><code>notification_closed</code></td>
<td>Notification closed</td>
<td>id</td>
</tr>
<tr>
<td><code>fade_speed_changed</code></td>
<td>Fade animation speed changed</td>
<td>old_speed, new_speed</td>
</tr>
<tr>
<td><code>fade_intensity_changed</code></td>
<td>Fade glow intensity changed</td>
<td>old_intensity, new_intensity</td>
</tr>
<tr>
<td><code>window_snapped</code></td>
<td>Window snapped to position</td>
<td>window, horizontal, vertical</td>
</tr>
<tr>
<td><code>audio_volume_changed</code></td>
<td>System audio volume changed</td>
<td>old_volume, new_volume</td>
</tr>
<tr>
<td><code>audio_mute_toggled</code></td>
<td>System audio mute toggled</td>
<td>muted</td>
</tr>
<tr>
<td><code>panel_visibility_changed</code></td>
<td>Panel shown or hidden</td>
<td>panel, visible</td>
</tr>
<tr>
<td><code>config_reloaded</code></td>
<td>Configuration reloaded</td>
<td>(none)</td>
</tr>
<tr>
<td><code>ai_response_received</code></td>
<td>AI command completed</td>
<td>prompt, response, success</td>
</tr>
<tr>
<td><code>exa_search_completed</code></td>
<td>Exa search completed</td>
<td>query, result_count, success</td>
</tr>
<tr>
<td><code>news_article_changed</code></td>
<td>News ticker article changed</td>
<td>old_index, new_index, title</td>
</tr>
<tr>
<td><code>demo_started</code></td>
<td>Demo mode started</td>
<td>(none)</td>
</tr>
<tr>
<td><code>demo_stopped</code></td>
<td>Demo mode stopped</td>
<td>(none)</td>
</tr>
<tr>
<td><code>demo_phase_changed</code></td>
<td>Demo phase changed</td>
<td>phase, phase_name</td>
</tr>
<tr>
<td><code>tutorial_started</code></td>
<td>Tutorial mode started</td>
<td>(none)</td>
</tr>
<tr>
<td><code>tutorial_stopped</code></td>
<td>Tutorial mode stopped</td>
<td>(none)</td>
</tr>
</tbody>
</table>
</div>
<h2 id="system">System Commands</h2>
<h3>get_status</h3>
<p>Get DWN status information.</p>
<div class="code-block">
<pre><code>// Request
{"command": "get_status"}
// Response
{
"status": "ok",
"version": "2.0.0",
"current_workspace": 0,
"client_count": 5
}</code></pre>
</div>
<h3>get_screen_info</h3>
<p>Get screen and monitor information.</p>
<div class="code-block">
<pre><code>// Request
{"command": "get_screen_info"}
// Response
{
"status": "ok",
"screen_width": 1920,
"screen_height": 1080,
"screen": 0,
"monitor_count": 1,
"monitors": [
{
"index": 0,
"x": 0,
"y": 0,
"width": 1920,
"height": 1080,
"primary": true
}
],
"usable_area": {
"x": 0,
"y": 32,
"width": 1920,
"height": 1048
}
}</code></pre>
</div>
<h3>run_command</h3>
<p>Spawn a process asynchronously.</p>
<div class="code-block">
<pre><code>// Request
{"command": "run_command", "exec": "firefox"}
// Response
{"status": "launched"}</code></pre>
</div>
<h3>show_desktop</h3>
<p>Toggle show desktop mode. Optionally set explicit state.</p>
<div class="code-block">
<pre><code>// Toggle
{"command": "show_desktop"}
// Set explicit state
{"command": "show_desktop", "state": true}
// Response
{
"status": "ok",
"desktop_shown": true
}</code></pre>
</div>
<h3>get_fade_settings</h3>
<p>Get current fade effect settings (speed and intensity).</p>
<div class="code-block">
<pre><code>// Request
{"command": "get_fade_settings"}
// Response
{
"status": "ok",
"fade_speed": 0.5,
"fade_intensity": 1.0
}</code></pre>
</div>
<h3>set_fade_speed</h3>
<p>Set fade animation speed (0.1 - 3.0, where 1.0 is normal speed).</p>
<div class="code-block">
<pre><code>// Request
{"command": "set_fade_speed", "speed": 1.5}
// Response
{
"status": "ok",
"fade_speed": 1.5
}</code></pre>
</div>
<h3>set_fade_intensity</h3>
<p>Set fade glow intensity (0.0 - 1.0, where 1.0 is full intensity).</p>
<div class="code-block">
<pre><code>// Request
{"command": "set_fade_intensity", "intensity": 0.8}
// Response
{
"status": "ok",
"fade_intensity": 0.8
}</code></pre>
</div>
<h2>Error Responses</h2>
<p>All commands may return errors:</p>
<div class="code-block">
<pre><code>{
"status": "error",
"message": "Window not found"
}
{
"status": "error",
"message": "Invalid parameter: workspace must be 0-8"
}
{
"status": "error",
"message": "Unknown command: invalid_command"
}</code></pre>
</div>
<footer>
<p>DWN Window Manager - retoor &lt;retoor@molodetz.nl&gt;</p>
</footer>
</div>
</main>
</div>
<script src="js/main.js"></script>
</body>
</html>