Skip to content

Instantly share code, notes, and snippets.

@hjanuschka
Last active February 16, 2026 01:22
Show Gist options
  • Select an option

  • Save hjanuschka/3177b6352e95d1b8d069bb91cc599848 to your computer and use it in GitHub Desktop.

Select an option

Save hjanuschka/3177b6352e95d1b8d069bb91cc599848 to your computer and use it in GitHub Desktop.
screen.orientation.lock() tester for DevTools device emulation (crbug.com/40807290)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>screen.orientation.lock() Test</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, monospace;
background: #1a1a2e;
color: #e0e0e0;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
}
h1 { color: #00d4ff; margin-bottom: 10px; font-size: 1.4em; }
.subtitle { color: #888; margin-bottom: 20px; font-size: 0.85em; }
.info-box {
background: #16213e;
border: 1px solid #0f3460;
border-radius: 8px;
padding: 16px;
width: 100%;
max-width: 500px;
margin-bottom: 16px;
}
.info-box h2 { color: #e94560; font-size: 1em; margin-bottom: 8px; }
.info-row {
display: flex;
justify-content: space-between;
padding: 4px 0;
font-size: 0.9em;
}
.info-label { color: #888; }
.info-value { color: #00d4ff; font-weight: bold; }
.buttons {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
width: 100%;
max-width: 500px;
margin-bottom: 16px;
}
button {
background: #0f3460;
color: #e0e0e0;
border: 1px solid #1a5276;
border-radius: 6px;
padding: 12px 8px;
cursor: pointer;
font-size: 0.85em;
transition: all 0.2s;
}
button:hover { background: #1a5276; border-color: #00d4ff; }
button:active { transform: scale(0.97); }
button.unlock-btn {
grid-column: 1 / -1;
background: #e94560;
border-color: #e94560;
}
button.unlock-btn:hover { background: #c0392b; }
#log {
background: #0d1117;
border: 1px solid #333;
border-radius: 8px;
padding: 12px;
width: 100%;
max-width: 500px;
height: 200px;
overflow-y: auto;
font-family: monospace;
font-size: 0.8em;
line-height: 1.6;
}
.log-entry { border-bottom: 1px solid #222; padding: 2px 0; }
.log-ok { color: #2ecc71; }
.log-err { color: #e94560; }
.log-info { color: #f39c12; }
.howto {
background: #16213e;
border: 1px solid #0f3460;
border-radius: 8px;
padding: 16px;
width: 100%;
max-width: 500px;
margin-top: 16px;
font-size: 0.78em;
line-height: 1.7;
color: #aaa;
}
.howto h3 { color: #00d4ff; margin-bottom: 8px; }
.howto code {
background: #0d1117;
padding: 1px 5px;
border-radius: 3px;
color: #f39c12;
}
.howto ol { padding-left: 20px; }
.howto li { margin-bottom: 4px; }
</style>
</head>
<body>
<h1>screen.orientation.lock() Tester</h1>
<p class="subtitle">Chromium Issue <a href="https://issues.chromium.org/issues/40807290" style="color:#00d4ff">40807290</a></p>
<div class="info-box">
<h2>Current Orientation State</h2>
<div class="info-row">
<span class="info-label">type:</span>
<span class="info-value" id="ori-type">--</span>
</div>
<div class="info-row">
<span class="info-label">angle:</span>
<span class="info-value" id="ori-angle">--</span>
</div>
<div class="info-row">
<span class="info-label">window size:</span>
<span class="info-value" id="win-size">--</span>
</div>
<div class="info-row">
<span class="info-label">screen size:</span>
<span class="info-value" id="scr-size">--</span>
</div>
<div class="info-row">
<span class="info-label">lock supported:</span>
<span class="info-value" id="lock-support">checking...</span>
</div>
</div>
<div class="buttons">
<button onclick="lockTo('portrait-primary')">Lock Portrait Primary</button>
<button onclick="lockTo('portrait-secondary')">Lock Portrait Secondary</button>
<button onclick="lockTo('landscape-primary')">Lock Landscape Primary</button>
<button onclick="lockTo('landscape-secondary')">Lock Landscape Secondary</button>
<button onclick="lockTo('portrait')">Lock Portrait (any)</button>
<button onclick="lockTo('landscape')">Lock Landscape (any)</button>
<button onclick="lockTo('natural')">Lock Natural</button>
<button onclick="lockTo('any')">Lock Any</button>
<button class="unlock-btn" onclick="doUnlock()">Unlock Orientation</button>
</div>
<div id="log"></div>
<div class="howto">
<h3>How to Test (with DevTools fix for issue 40807290)</h3>
<ol>
<li>Open Chrome and navigate to this file: <code>file:///home/chrome/lock.html</code></li>
<li>Open DevTools (<code>F12</code> or <code>Ctrl+Shift+I</code>)</li>
<li>Click the <strong>device toolbar</strong> toggle (phone icon) to enable mobile emulation</li>
<li>Select a device (e.g. "iPhone 14 Pro Max") or use "Responsive" mode</li>
<li>Click any <strong>"Lock ..."</strong> button on this page</li>
</ol>
<h3>Expected Results</h3>
<ol>
<li><strong>Before fix:</strong> Every lock attempt logs <code style="color:#e94560">NotSupportedError: screen.orientation.lock() is not available on this device</code></li>
<li><strong>After fix (Milestone 1):</strong> Lock succeeds, orientation changes, log shows <code style="color:#2ecc71">OK</code></li>
<li><strong>After fix (Milestone 2):</strong> The <strong>rotate button</strong> in the DevTools device toolbar is <em>disabled</em> while orientation is locked</li>
</ol>
<h3>Verifying Without the Fix</h3>
<p>Open this page in current Chrome stable/canary with device emulation on. Click any Lock button. You will see the <code style="color:#e94560">NotSupportedError</code> -- that confirms the bug.</p>
</div>
<script>
const logEl = document.getElementById('log');
const oriType = document.getElementById('ori-type');
const oriAngle = document.getElementById('ori-angle');
const winSize = document.getElementById('win-size');
const scrSize = document.getElementById('scr-size');
const lockSupport = document.getElementById('lock-support');
function log(msg, cls) {
const d = document.createElement('div');
d.className = 'log-entry ' + (cls || '');
const ts = new Date().toLocaleTimeString('en', {hour12:false, hour:'2-digit', minute:'2-digit', second:'2-digit'});
d.textContent = `[${ts}] ${msg}`;
logEl.prepend(d);
}
function updateInfo() {
const o = screen.orientation;
oriType.textContent = o.type;
oriAngle.textContent = o.angle + 'deg';
winSize.textContent = window.innerWidth + ' x ' + window.innerHeight;
scrSize.textContent = screen.width + ' x ' + screen.height;
}
// Detect lock support by attempting a harmless lock
async function checkLockSupport() {
try {
// lock('any') is the least restrictive -- if it works, lock is supported
await screen.orientation.lock('any');
screen.orientation.unlock();
lockSupport.textContent = 'YES';
lockSupport.style.color = '#2ecc71';
} catch (e) {
if (e.name === 'NotSupportedError') {
lockSupport.textContent = 'NO (NotSupportedError)';
lockSupport.style.color = '#e94560';
} else if (e.name === 'SecurityError') {
// SecurityError means lock IS supported but requires fullscreen/user gesture
lockSupport.textContent = 'YES (needs gesture/fullscreen)';
lockSupport.style.color = '#f39c12';
} else {
lockSupport.textContent = 'UNKNOWN (' + e.name + ')';
lockSupport.style.color = '#f39c12';
}
}
}
async function lockTo(orientation) {
log(`Calling screen.orientation.lock("${orientation}")...`, 'log-info');
try {
await screen.orientation.lock(orientation);
log(`OK -- locked to "${orientation}". Now: type=${screen.orientation.type}, angle=${screen.orientation.angle}`, 'log-ok');
updateInfo();
lockSupport.textContent = 'YES';
lockSupport.style.color = '#2ecc71';
} catch (e) {
log(`FAIL -- ${e.name}: ${e.message}`, 'log-err');
}
}
function doUnlock() {
log('Calling screen.orientation.unlock()...', 'log-info');
try {
screen.orientation.unlock();
log(`OK -- unlocked. Now: type=${screen.orientation.type}, angle=${screen.orientation.angle}`, 'log-ok');
updateInfo();
} catch (e) {
log(`FAIL -- ${e.name}: ${e.message}`, 'log-err');
}
}
screen.orientation.addEventListener('change', () => {
log(`EVENT orientation change -> type=${screen.orientation.type}, angle=${screen.orientation.angle}`, 'log-info');
updateInfo();
});
window.addEventListener('resize', updateInfo);
// Init
updateInfo();
checkLockSupport();
log('Page loaded. Enable DevTools device emulation and click a Lock button.', 'log-info');
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment