From a2057eeb59958000a36f87519cd9b8690f24f451 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Dec 2025 20:26:00 +0000 Subject: [PATCH 1/3] Initial plan From 10100d8bb9cf9ff16ae254d09527c4c82db2ce1b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Dec 2025 20:32:16 +0000 Subject: [PATCH 2/3] Fix fullscreen user gesture requirement in multi-monitor mode Remove programmatic fullscreen requests that violate browser security policies. Child windows can no longer enter fullscreen automatically via BroadcastChannel as this is not considered a user gesture. Users must double-click each window to enter fullscreen mode. Co-authored-by: ap0ught <41078+ap0ught@users.noreply.github.com> --- js/fullscreen.js | 37 ++++++++++++++++++++++++++++++++++--- js/multi-monitor.js | 24 ++++++++++++++++-------- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/js/fullscreen.js b/js/fullscreen.js index 86ae32c..e82f8f8 100644 --- a/js/fullscreen.js +++ b/js/fullscreen.js @@ -183,16 +183,47 @@ export function setupFullscreenToggle(element) { const success = await multiMonitorManager.spawnWindows(matrixConfig); if (success) { - // Request fullscreen on all spawned windows + // Notify child windows (they must enter fullscreen manually via double-click) await multiMonitorManager.requestFullscreenAll(); + console.log("Multi-monitor windows opened. Double-click each window to enter fullscreen."); + + // Request fullscreen on main window + try { + const result = requestFullscreen(element); + if (result && result.catch) { + result.catch((error) => { + console.error("Fullscreen request failed:", error.message); + }); + } + } catch (error) { + console.error("Fullscreen request failed:", error.message); + } } else { // Fall back to single-screen fullscreen console.warn("Multi-monitor fullscreen failed, falling back to single screen"); - requestFullscreen(element); + try { + const result = requestFullscreen(element); + if (result && result.catch) { + result.catch((error) => { + console.error("Fullscreen request failed:", error.message); + }); + } + } catch (error) { + console.error("Fullscreen request failed:", error.message); + } } } else { // Normal single-screen fullscreen - requestFullscreen(element); + try { + const result = requestFullscreen(element); + if (result && result.catch) { + result.catch((error) => { + console.error("Fullscreen request failed:", error.message); + }); + } + } catch (error) { + console.error("Fullscreen request failed:", error.message); + } } } else { // In fullscreen, exit it diff --git a/js/multi-monitor.js b/js/multi-monitor.js index d460c52..510e792 100644 --- a/js/multi-monitor.js +++ b/js/multi-monitor.js @@ -302,32 +302,40 @@ export default class MultiMonitorManager { /** * Request fullscreen on all spawned windows + * + * NOTE: Due to browser security restrictions, child windows cannot enter + * fullscreen programmatically via BroadcastChannel. This method notifies + * child windows, but users must manually double-click each window to enter + * fullscreen mode. */ async requestFullscreenAll() { - // Use broadcast channel to tell all child windows to enter fullscreen + // Use broadcast channel to notify child windows + // They will log a message prompting the user to double-click if (this.broadcastChannel) { this.broadcastChannel.postMessage({ type: "requestFullscreen" }); } - // Child windows will handle their own fullscreen requests + // Note: Child windows cannot enter fullscreen automatically return true; } /** * Handle fullscreen request from child window * This is called by child windows when they receive the broadcast + * + * NOTE: Due to browser security restrictions, fullscreen cannot be requested + * programmatically via BroadcastChannel as it's not considered a user gesture. + * Child windows must enter fullscreen manually (e.g., via double-click). */ static handleChildFullscreenRequest(canvas) { const channel = new BroadcastChannel("matrix-multi-monitor"); channel.addEventListener("message", (event) => { if (event.data.type === "requestFullscreen") { - // Request fullscreen on this child window - if (canvas.requestFullscreen) { - canvas.requestFullscreen().catch((err) => { - console.error("Fullscreen request failed:", err); - }); - } + // Cannot request fullscreen programmatically via broadcast message + // as it's not considered a user gesture by the browser. + // Users should double-click each window to enter fullscreen. + console.log("Fullscreen request received. Double-click the window to enter fullscreen mode."); } else if (event.data.type === "exitFullscreen") { // Exit fullscreen on this child window if (document.fullscreenElement) { From 7f8d3320ef57b97caf4b8c0e20dd5e19d7e0dc26 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Dec 2025 20:34:25 +0000 Subject: [PATCH 3/3] Update MULTI_MONITOR.md to document browser security restrictions Add detailed documentation about browser security policies that prevent programmatic fullscreen requests. Clarify that users must manually double-click each child window to enter fullscreen mode. Co-authored-by: ap0ught <41078+ap0ught@users.noreply.github.com> --- MULTI_MONITOR.md | 70 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 12 deletions(-) diff --git a/MULTI_MONITOR.md b/MULTI_MONITOR.md index c606101..794a5c1 100644 --- a/MULTI_MONITOR.md +++ b/MULTI_MONITOR.md @@ -29,7 +29,10 @@ The Matrix Digital Rain now supports fullscreen across multiple displays using t 4. Check either: - **Independent Instances** - for varied effects across screens - **Uniform Config** - for synchronized effects across screens -5. Double-click anywhere on the canvas to activate fullscreen across all displays +5. Double-click anywhere on the canvas to activate multi-monitor mode + - The main window will attempt to enter fullscreen + - Additional windows will open on other displays + - **Important**: You must manually double-click each child window to enter fullscreen due to browser security restrictions #### Via URL Parameters @@ -100,8 +103,9 @@ The implementation consists of: - Enumerates all connected displays - Opens a new window on each display with current URL - Each window initializes with its own random seed -4. BroadcastChannel coordinates fullscreen requests -5. Each window enters fullscreen independently +4. Main window enters fullscreen +5. Child windows log a message prompting user to double-click for fullscreen +6. User must manually double-click each child window to activate fullscreen #### Uniform Mode Flow @@ -113,8 +117,10 @@ The implementation consists of: - Serializes current config to URL parameters - Opens a new window on each display with serialized config - All windows start with identical settings -4. BroadcastChannel coordinates fullscreen requests -5. Natural drift occurs from random glyph timing +4. Main window enters fullscreen +5. Child windows log a message prompting user to double-click for fullscreen +6. User must manually double-click each child window to activate fullscreen +7. Natural drift occurs from random glyph timing #### Exit Flow @@ -139,7 +145,7 @@ For uniform mode, the following config parameters are serialized to URL: The system uses `BroadcastChannel("matrix-multi-monitor")` for coordination: ```javascript -// Request fullscreen on all windows +// Notify child windows (they must manually enter fullscreen via double-click) { type: "requestFullscreen" } // Exit fullscreen on all windows @@ -152,6 +158,8 @@ The system uses `BroadcastChannel("matrix-multi-monitor")` for coordination: { type: "windowClosed", screenIndex: } ``` +**Note**: Due to browser security restrictions, the `requestFullscreen` message cannot actually trigger fullscreen on child windows. It only serves as a notification. Users must manually double-click each window. + ## Error Handling The system gracefully handles various error conditions: @@ -171,14 +179,51 @@ The system gracefully handles various error conditions: - Shows alert: "Multi-monitor fullscreen requires at least 2 displays" - Falls back to standard single-screen fullscreen -### Window Spawn Failure -- Handles popup blocker interference -- Logs failures to console -- Continues with successfully opened windows +### Fullscreen Request Failure +- Fullscreen must be triggered by a direct user gesture (click, key press) +- Programmatic fullscreen requests fail with "Permissions check failed" +- Child windows cannot enter fullscreen automatically via message passing +- Solution: Users must double-click each child window -## Backward Compatibility +## Browser Security Restrictions + +Modern browsers enforce strict security policies around the Fullscreen API to prevent malicious websites from hijacking the user's screen. These restrictions affect multi-monitor fullscreen: + +### User Gesture Requirement + +The `requestFullscreen()` method can **only** be called in direct response to a user interaction event (click, key press, touch). The browser considers these as valid user gestures: + +- ✅ Mouse clicks (`click`, `dblclick`) +- ✅ Keyboard events (`keydown`, `keyup`, `keypress`) +- ✅ Touch events (`touchend`) + +The browser **does not** consider these as user gestures: + +- ❌ Timers (`setTimeout`, `setInterval`) +- ❌ Promises resolving asynchronously +- ❌ Message passing (`postMessage`, `BroadcastChannel`) +- ❌ Page load events (`DOMContentLoaded`, `load`) +- ❌ Network responses (`fetch`, `XMLHttpRequest`) -The feature is fully backward compatible: +### Impact on Multi-Monitor Fullscreen + +When the user double-clicks the main window: +1. ✅ The main window can enter fullscreen (direct user gesture) +2. ❌ Child windows cannot enter fullscreen via BroadcastChannel message (not a user gesture in that window) + +This is why users must manually double-click each child window to activate fullscreen on multiple displays. + +### Why This Matters + +This security restriction prevents malicious scenarios like: +- Websites automatically entering fullscreen without user consent +- Phishing attacks that mimic system dialogs in fullscreen mode +- Unwanted fullscreen popups or advertisements +- Cross-window fullscreen hijacking attempts + +The browser vendors (Chrome, Firefox, Safari) all enforce these restrictions to protect users. + +## Backward Compatibility - **Single-monitor systems**: Work exactly as before - **Existing URL parameters**: All respected and functional @@ -225,6 +270,7 @@ The feature is fully backward compatible: 3. **Popup Blockers**: May interfere with window spawning (users must allow popups) 4. **No Explicit Sync**: Uniform mode uses same initial config but doesn't maintain frame-perfect synchronization 5. **Wake Lock**: Each window manages its own wake lock independently +6. **Manual Fullscreen**: Due to browser security policies, each child window must be manually set to fullscreen by double-clicking it. Programmatic fullscreen requests across windows via BroadcastChannel are not allowed as they're not considered user gestures ## Future Enhancements