Window Communication (Bridge)
Use dmn.bridge to send and receive messages between main and overlay windows.
Key Uses
- 🪟 Window communication: Data transfer between main ↔ overlay
- 🔌 Plugin communication: Data sharing between plugins in same or different windows
- 📡 Broadcast: Send messages to all plugins in all windows
API Reference
send(type, data)
Broadcast message to all windows.
await dmn.bridge.send("WPM_UPDATE", { value: 80, max: 200 });sendTo(target, type, data)
Send message to specific window only.
// Send to overlay only
await dmn.bridge.sendTo("overlay", "THEME_CHANGED", { theme: "dark" });
// Send to main only
await dmn.bridge.sendTo("main", "KEY_PRESSED", { key: "KeyD" });Only the target window’s listeners fire. In OBS mode the OBS browser source stands in for the overlay window, so it receives messages sent to "overlay".
on(type, listener)
Subscribe to specific message type.
const unsub = dmn.bridge.on("WPM_UPDATE", (data) => {
console.log("WPM:", data.value);
});
// Unsubscribe
unsub();once(type, listener)
Receive specific message type only once.
dmn.bridge.once("INIT_COMPLETE", (data) => {
console.log("Initialization complete:", data);
});onAny(listener)
Receive all message types. Useful for debugging.
const unsub = dmn.bridge.onAny((type, data) => {
console.log(`[Bridge] ${type}:`, data);
});off(type, listener?)
Unsubscribe from messages.
// Unsubscribe specific listener
dmn.bridge.off("WPM_UPDATE", myListener);
// Unsubscribe all listeners for that type
dmn.bridge.off("WPM_UPDATE");Usage Patterns
One-way Event Sending
// Send from overlay
await dmn.bridge.send("KEY_PRESSED", { key: "KeyD" });
// Receive in main
dmn.bridge.on("KEY_PRESSED", ({ key }) => {
console.log(`${key} pressed`);
});Real-time Data Sync
// === Overlay: Calculate KPS and send ===
// @id kps-sender
if (dmn.window.type !== "overlay") return;
let count = 0;
dmn.keys.onKeyState(({ state }) => {
if (state === "DOWN") count++;
});
setInterval(() => {
dmn.bridge.sendTo("main", "KPS_UPDATE", { kps: count });
count = 0;
}, 100);// === Main: Display KPS ===
// @id kps-display
if (dmn.window.type !== "main") return;
const display = document.createElement("div");
display.textContent = "KPS: 0";
document.body.appendChild(display);
dmn.bridge.on("KPS_UPDATE", ({ kps }) => {
display.textContent = `KPS: ${kps}`;
});
dmn.plugin.registerCleanup(() => {
display.remove();
});Request-Response Pattern
// === Main: Request data ===
dmn.bridge.send("REQUEST_STATS", { type: "current" });
dmn.bridge.once("RESPONSE_STATS", (stats) => {
console.log("Stats:", stats);
});// === Overlay: Handle request and respond ===
dmn.bridge.on("REQUEST_STATS", ({ type }) => {
const stats = {
kps: currentKPS,
totalKeys: totalKeyCount,
uptime: Date.now() - startTime,
};
dmn.bridge.sendTo("main", "RESPONSE_STATS", stats);
});Data Sharing Between Plugins
// === Data provider (data-provider.js) ===
// @id data-provider
const sharedData = { score: 0, level: 1 };
function updateData(score, level) {
sharedData.score = score;
sharedData.level = level;
dmn.bridge.send("SHARED_DATA_UPDATE", sharedData);
}
// Example: Increase score every second
setInterval(() => {
updateData(sharedData.score + 10, sharedData.level);
}, 1000);// === Data consumer A (consumer-a.js) ===
// @id consumer-a
dmn.bridge.on("SHARED_DATA_UPDATE", (data) => {
console.log("[Consumer A] Data:", data);
updateUI(data.score);
});// === Data consumer B (consumer-b.js) ===
// @id consumer-b
// Multiple plugins can receive the same message simultaneously
dmn.bridge.on("SHARED_DATA_UPDATE", (data) => {
console.log("[Consumer B] Data:", data);
displayLevel(data.level);
});defineElement and Bridge Integration
// @id bridge-kps-panel
dmn.plugin.defineElement({
name: "Bridge KPS Panel",
maxInstances: 1,
messages: {
ko: { "menu.create": "KPS 패널 생성", "menu.delete": "KPS 패널 삭제" },
en: {
"menu.create": "Create KPS Panel",
"menu.delete": "Delete KPS Panel",
},
},
contextMenu: {
create: "menu.create",
delete: "menu.delete",
},
template: (state, settings, { html }) => html`
<div
style="
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 16px;
border-radius: 8px;
"
>
<div style="font-size: 24px; font-weight: bold;">
${state.kps ?? 0} KPS
</div>
<div
style="display: flex; gap: 2px; height: 30px; align-items: flex-end;"
>
${(state.history ?? []).map(
(v) => html`
<div
style="
flex: 1;
height: ${v}%;
background: #86EFAC;
border-radius: 2px;
"
></div>
`,
)}
</div>
</div>
`,
// ... onMount implementation
});