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" });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
});