agentmux_cef/
srv_event_bridge.rs

1// Copyright 2026, AgentMux Corp.
2// SPDX-License-Identifier: Apache-2.0
3//
4// Phase E.2c.5a — host outbound JS bridge for srv typed events.
5//
6// Parallel to `launcher_event_bridge`, but for the srv reducer's
7// pipe (workspace / tab / block / layout lifecycle). Single function
8// `dispatch_to_renderers(state, event)` called from `srv_ipc`'s
9// read loop after each line is parsed.
10//
11// Renderer-side handler: `window.__agentmux_srv_event(<json>)`. The
12// renderer dispatcher (separate frontend PR — E.2c.5b) installs that
13// handler and routes events into atom domains.
14//
15// Filtering: pool windows (`window-pool-*`) and browser-pane child
16// HWNDs (`browser-pane-*`) are skipped — they have no UI.
17
18use std::sync::Arc;
19
20use agentmux_common::ipc::Event;
21use cef::{CefString, ImplBrowser, ImplFrame};
22
23/// Forward an srv event to every top-level renderer.
24pub fn dispatch_to_renderers(state: &Arc<crate::state::AppState>, event: &Event) {
25    let json = match serde_json::to_string(event) {
26        Ok(s) => s,
27        Err(e) => {
28            tracing::warn!(
29                target: "srv-event-bridge",
30                "[srv-event-bridge] serialize failed: {}",
31                e
32            );
33            return;
34        }
35    };
36
37    let script = format!(
38        "if (window.__agentmux_srv_event) {{ try {{ window.__agentmux_srv_event({}) }} catch(e) {{ console.error('[srv-event] dispatch failed', e) }} }}",
39        json
40    );
41    let code = CefString::from(script.as_str());
42    let url = CefString::from("");
43
44    // Phase H.2.b — reducer-aware iteration with fallback.
45    for (label, browser) in state.list_browsers() {
46        if label.starts_with("window-pool-") || label.starts_with("browser-pane-") {
47            continue;
48        }
49        if let Some(frame) = browser.main_frame() {
50            frame.execute_java_script(Some(&code), Some(&url), 0);
51        }
52    }
53}