markdown · 3401 bytes Raw Blame History

Phase 4: Daemon Mode & gar Integration

Goal

Implement daemon mode with IPC server, integrate with gar window manager for workspace-aware wallpapers.

Tasks

4.1 Daemon Mode

  • Daemonize process (fork, setsid, etc.)
  • PID file management
  • Signal handling (SIGHUP for reload, SIGTERM for shutdown)
  • Graceful shutdown with resource cleanup

4.2 IPC Server

  • Unix socket at $XDG_RUNTIME_DIR/garbg.sock
  • JSON lines protocol
  • Command parsing and dispatch
  • Response serialization
  • Client connection management

4.3 IPC Commands

  • set - Set wallpaper
  • next / prev - Slideshow navigation
  • random - Random wallpaper from source
  • reload - Reload configuration
  • pause / resume - Animation/slideshow control
  • status - Get current state
  • subscribe - Event subscription

4.4 gar IPC Client

  • Connect to gar's IPC socket
  • Subscribe to workspace events
  • Subscribe to monitor events
  • Parse gar's JSON event format

4.5 Per-Workspace Wallpapers

  • Map workspace ID to wallpaper config
  • Switch wallpaper on workspace change
  • Smooth transition (instant, per design decision)
  • Fallback to default wallpaper

4.6 Slideshow/Rotation

  • Timer-based rotation
  • Configurable interval
  • Random or sequential ordering
  • Per-source playlist management

Deliverables

  • garbg daemon starts background daemon
  • garbgctl set /path/to/image.png sends command to daemon
  • Changing workspaces in gar changes wallpaper
  • Slideshow rotates wallpapers at configured interval

IPC Protocol

Commands (Client -> Server)

{"command": "set", "source": "/path/to/image.png", "mode": "fill"}
{"command": "next"}
{"command": "prev"}
{"command": "random"}
{"command": "reload"}
{"command": "pause"}
{"command": "resume"}
{"command": "status"}
{"command": "subscribe", "events": ["wallpaper_changed", "slideshow_advanced"]}

Responses (Server -> Client)

{"success": true}
{"success": true, "data": {"current": "/path/to/image.png", "mode": "fill", "paused": false}}
{"success": false, "error": "File not found"}

Events (Server -> Subscribed Clients)

{"event": "wallpaper_changed", "source": "/path/to/new.png", "workspace": 1}
{"event": "slideshow_advanced", "current": 5, "total": 20}
{"event": "error", "message": "Failed to fetch remote image"}

gar Event Handling

// Subscribe to gar workspace events
let subscribe_msg = json!({
    "command": "subscribe",
    "events": ["workspace"]
});

// Handle workspace change
fn handle_gar_event(&mut self, event: GarEvent) {
    match event {
        GarEvent::Workspace { current, .. } => {
            if let Some(config) = self.config.workspaces.get(&current) {
                self.set_wallpaper(&config.source, config.mode);
            }
        }
        _ => {}
    }
}

Files Modified/Created

  • /garbg/garbg/src/daemon/mod.rs - Daemon module
  • /garbg/garbg/src/daemon/state.rs - Daemon state management
  • /garbg/garbg/src/daemon/event_loop.rs - Main event loop
  • /garbg/garbg/src/daemon/signals.rs - Signal handling
  • /garbg/garbg/src/ipc/mod.rs - IPC module
  • /garbg/garbg/src/ipc/server.rs - IPC server
  • /garbg/garbg/src/ipc/protocol.rs - Command/Response types
  • /garbg/garbg/src/ipc/gar_client.rs - gar IPC client
View source
1 # Phase 4: Daemon Mode & gar Integration
2
3 ## Goal
4 Implement daemon mode with IPC server, integrate with gar window manager for workspace-aware wallpapers.
5
6 ## Tasks
7
8 ### 4.1 Daemon Mode
9 - [ ] Daemonize process (fork, setsid, etc.)
10 - [ ] PID file management
11 - [ ] Signal handling (SIGHUP for reload, SIGTERM for shutdown)
12 - [ ] Graceful shutdown with resource cleanup
13
14 ### 4.2 IPC Server
15 - [ ] Unix socket at `$XDG_RUNTIME_DIR/garbg.sock`
16 - [ ] JSON lines protocol
17 - [ ] Command parsing and dispatch
18 - [ ] Response serialization
19 - [ ] Client connection management
20
21 ### 4.3 IPC Commands
22 - [ ] `set` - Set wallpaper
23 - [ ] `next` / `prev` - Slideshow navigation
24 - [ ] `random` - Random wallpaper from source
25 - [ ] `reload` - Reload configuration
26 - [ ] `pause` / `resume` - Animation/slideshow control
27 - [ ] `status` - Get current state
28 - [ ] `subscribe` - Event subscription
29
30 ### 4.4 gar IPC Client
31 - [ ] Connect to gar's IPC socket
32 - [ ] Subscribe to workspace events
33 - [ ] Subscribe to monitor events
34 - [ ] Parse gar's JSON event format
35
36 ### 4.5 Per-Workspace Wallpapers
37 - [ ] Map workspace ID to wallpaper config
38 - [ ] Switch wallpaper on workspace change
39 - [ ] Smooth transition (instant, per design decision)
40 - [ ] Fallback to default wallpaper
41
42 ### 4.6 Slideshow/Rotation
43 - [ ] Timer-based rotation
44 - [ ] Configurable interval
45 - [ ] Random or sequential ordering
46 - [ ] Per-source playlist management
47
48 ## Deliverables
49 - `garbg daemon` starts background daemon
50 - `garbgctl set /path/to/image.png` sends command to daemon
51 - Changing workspaces in gar changes wallpaper
52 - Slideshow rotates wallpapers at configured interval
53
54 ## IPC Protocol
55
56 ### Commands (Client -> Server)
57
58 ```json
59 {"command": "set", "source": "/path/to/image.png", "mode": "fill"}
60 {"command": "next"}
61 {"command": "prev"}
62 {"command": "random"}
63 {"command": "reload"}
64 {"command": "pause"}
65 {"command": "resume"}
66 {"command": "status"}
67 {"command": "subscribe", "events": ["wallpaper_changed", "slideshow_advanced"]}
68 ```
69
70 ### Responses (Server -> Client)
71
72 ```json
73 {"success": true}
74 {"success": true, "data": {"current": "/path/to/image.png", "mode": "fill", "paused": false}}
75 {"success": false, "error": "File not found"}
76 ```
77
78 ### Events (Server -> Subscribed Clients)
79
80 ```json
81 {"event": "wallpaper_changed", "source": "/path/to/new.png", "workspace": 1}
82 {"event": "slideshow_advanced", "current": 5, "total": 20}
83 {"event": "error", "message": "Failed to fetch remote image"}
84 ```
85
86 ## gar Event Handling
87
88 ```rust
89 // Subscribe to gar workspace events
90 let subscribe_msg = json!({
91 "command": "subscribe",
92 "events": ["workspace"]
93 });
94
95 // Handle workspace change
96 fn handle_gar_event(&mut self, event: GarEvent) {
97 match event {
98 GarEvent::Workspace { current, .. } => {
99 if let Some(config) = self.config.workspaces.get(&current) {
100 self.set_wallpaper(&config.source, config.mode);
101 }
102 }
103 _ => {}
104 }
105 }
106 ```
107
108 ## Files Modified/Created
109 - `/garbg/garbg/src/daemon/mod.rs` - Daemon module
110 - `/garbg/garbg/src/daemon/state.rs` - Daemon state management
111 - `/garbg/garbg/src/daemon/event_loop.rs` - Main event loop
112 - `/garbg/garbg/src/daemon/signals.rs` - Signal handling
113 - `/garbg/garbg/src/ipc/mod.rs` - IPC module
114 - `/garbg/garbg/src/ipc/server.rs` - IPC server
115 - `/garbg/garbg/src/ipc/protocol.rs` - Command/Response types
116 - `/garbg/garbg/src/ipc/gar_client.rs` - gar IPC client