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}