-
-
Notifications
You must be signed in to change notification settings - Fork 308
Description
We are experiencing a focus/input issue in HTML5 builds generated by Solar2D when running on Android 16 (modern mobile browsers).
After extensive testing, the problem appears to be caused by the default focus-handling code appended to index.html by Solar2D:
<script>
window.addEventListener('load', function(){ window.focus() });
window.addEventListener('mousedown', function () {
document.activeElement.blur();
window.focus();
}, true);
</script>
Problem Summary
On modern mobile browsers (tested on Android 16), forcing window.focus() — especially combined with document.activeElement.blur() — can break input handling after the game loses focus due to interaction with external UI elements.
Scenario
- The HTML5 game runs embedded inside a platform that injects UI elements outside the canvas (e.g., status bar, overlay controls, exit button, etc.).
- The user taps one of those external UI elements.
- The browser correctly shifts focus away from the canvas.
- The user taps the canvas again to resume gameplay.
Expected behavior:
The game should regain focus and continue receiving input normally.
Actual behavior:
The canvas stops receiving input events permanently.
The game appears frozen and cannot recover, regardless of further taps.
The issue is 100% reproducible in embedded environments such as YouTube Playables on Android 16.
Root Cause (Suspected)
Modern mobile browsers heavily restrict window.focus() and focus manipulation unless triggered by trusted user gestures.
The current template:
- Forces
window.focus()on load - Blurs
document.activeElement - Forces
window.focus()again on every mousedown
This appears to interfere with the browser’s focus lifecycle after external UI interactions, leaving the page in an inconsistent focus state.
In short:
window.focus() is no longer reliable behavior in modern mobile environments.
Proposed Fix
Instead of managing focus at the window level, focus management should be limited to the canvas element itself, and only in response to real user interaction.
Replacing the default logic with canvas-based focus handling resolves the issue completely:
<script>
const canvas = document.getElementById('canvas');
// Allow canvas to receive focus
canvas.tabIndex = 0;
// Focus on load
window.addEventListener('load', () => {
canvas.focus();
});
// Refocus only on real user interaction with the canvas
canvas.addEventListener('pointerdown', () => {
canvas.focus();
});
</script>
Why this works
- No forced
window.focus() - No aggressive
blur()calls - Focus changes occur only on legitimate user interaction
- Compatible with modern mobile browser restrictions
- Fully fixes the freeze after external UI interaction
After this change:
- Interacting with external UI elements does NOT permanently break input
- Tapping the canvas restores gameplay reliably
- No freezes observed
Suggested Action
Consider updating the default HTML5 template to:
Remove window.focus() calls
Remove global blur() logic
Handle focus strictly at the canvas level
Tie focus restoration to trusted pointer events
This approach appears to be safer and more future-proof for modern mobile browsers and embedded environments.
Environment
- Solar2D: HTML5 build
- Platform: Android 16
- Browser: Modern mobile Chromium-based browser
- Reproducible in: Embedded environments (e.g., YouTube Playables)