feat: Send Key dropdown for browser-intercepted keys
Adds a "Send Key" dropdown menu to the console toolbar for keys that browsers intercept before JavaScript can capture them (Print Screen, Scroll Lock, Pause/Break). Also includes Escape, Tab, Caps Lock, Num Lock, and Ctrl+Alt+Del. Each menu item sends a press+release scancode pair directly over the WebSocket, bypassing browser key capture entirely. This enables activating downstream KVM switch menus (e.g., Avocent OSCAR via Print Screen) from the blekin interface. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,21 @@ export function mountConsole(el: HTMLElement, s: SessionInfo) {
|
||||
<div class="toolbar">
|
||||
<span>${s.boardName}</span>
|
||||
<select id="port-select" title="Switch KVM port"></select>
|
||||
<button id="btn-cad">Ctrl+Alt+Del</button>
|
||||
<div class="sendkey-wrap">
|
||||
<button id="btn-sendkey">Send Key ▾</button>
|
||||
<div class="sendkey-menu" id="sendkey-menu" hidden>
|
||||
<button data-sc="72">Print Screen</button>
|
||||
<button data-sc="73">Scroll Lock</button>
|
||||
<button data-sc="74">Pause / Break</button>
|
||||
<hr />
|
||||
<button data-sc="59">Escape</button>
|
||||
<button data-sc="14">Tab</button>
|
||||
<button data-sc="28">Caps Lock</button>
|
||||
<button data-sc="85">Num Lock</button>
|
||||
<hr />
|
||||
<button data-cad="1">Ctrl + Alt + Del</button>
|
||||
</div>
|
||||
</div>
|
||||
<button id="btn-fs">Fullscreen</button>
|
||||
<span class="status" id="status">connecting...</span>
|
||||
</div>
|
||||
@@ -228,11 +242,40 @@ function wireInputHandlers() {
|
||||
}
|
||||
|
||||
function wireToolbar() {
|
||||
document.getElementById('btn-cad')?.addEventListener('click', () => {
|
||||
if (ws?.readyState === WebSocket.OPEN) ws.send(makeCtrlAltDel())
|
||||
document.getElementById('canvas')?.focus()
|
||||
// Send Key dropdown
|
||||
const sendKeyBtn = document.getElementById('btn-sendkey')!
|
||||
const sendKeyMenu = document.getElementById('sendkey-menu')!
|
||||
|
||||
sendKeyBtn.addEventListener('click', (e) => {
|
||||
e.stopPropagation()
|
||||
sendKeyMenu.hidden = !sendKeyMenu.hidden
|
||||
})
|
||||
|
||||
// Close menu on outside click
|
||||
document.addEventListener('click', () => { sendKeyMenu.hidden = true })
|
||||
sendKeyMenu.addEventListener('click', (e) => e.stopPropagation())
|
||||
|
||||
sendKeyMenu.querySelectorAll('button[data-sc]').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const sc = parseInt((btn as HTMLElement).dataset.sc!)
|
||||
if (ws?.readyState === WebSocket.OPEN) {
|
||||
ws.send(makeKeyPress(sc))
|
||||
ws.send(makeKeyRelease(sc))
|
||||
}
|
||||
sendKeyMenu.hidden = true
|
||||
document.getElementById('canvas')?.focus()
|
||||
})
|
||||
})
|
||||
|
||||
sendKeyMenu.querySelectorAll('button[data-cad]').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
if (ws?.readyState === WebSocket.OPEN) ws.send(makeCtrlAltDel())
|
||||
sendKeyMenu.hidden = true
|
||||
document.getElementById('canvas')?.focus()
|
||||
})
|
||||
})
|
||||
|
||||
// Fullscreen
|
||||
document.getElementById('btn-fs')?.addEventListener('click', () => {
|
||||
const shell = document.querySelector('.shell')
|
||||
if (document.fullscreenElement) document.exitFullscreen()
|
||||
|
||||
@@ -126,6 +126,44 @@ body {
|
||||
.toolbar .status { margin-left: auto; color: #888; }
|
||||
.toolbar .status.connected { color: #4a7c59; }
|
||||
|
||||
/* Send Key dropdown */
|
||||
.sendkey-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sendkey-menu {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
background: #2a2a2a;
|
||||
border: 1px solid #444;
|
||||
border-radius: 4px;
|
||||
padding: 0.25rem 0;
|
||||
min-width: 160px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.sendkey-menu button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0.35rem 0.75rem;
|
||||
border: none;
|
||||
background: none;
|
||||
color: #ccc;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.sendkey-menu button:hover { background: #383838; }
|
||||
|
||||
.sendkey-menu hr {
|
||||
border: none;
|
||||
border-top: 1px solid #3a3a3a;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
/* Console canvas */
|
||||
.console-wrap {
|
||||
flex: 1;
|
||||
|
||||
Reference in New Issue
Block a user