fix(pi3): auto-focus terminal + log serial input bytes

PiTerminal didn't call term.focus() on mount, so xterm.js stayed
passive — onData only fires when the DOM element has focus.  Users
saw the boot prompt but their keystrokes went to whatever element
held focus when they clicked Run (canvas, code editor), never
reaching the bridge.  Calling focus() right after fit() makes the
prompt receive input the moment it's visible.

The qemu_manager change adds INFO-level logging when serial_input
WebSocket messages reach send_serial_bytes — useful diagnostic for
future Pi3 input problems (proves whether bytes reached the backend
before we look at TTY / kernel / PL011 wiring).
This commit is contained in:
davidmonterocrespo24 2026-05-17 16:37:56 +02:00
parent adad446518
commit 09a227466a
2 changed files with 17 additions and 6 deletions

View File

@ -118,12 +118,18 @@ class QemuManager:
async def send_serial_bytes(self, client_id: str, data: bytes) -> None:
inst = self._instances.get(client_id)
if inst and inst._serial_writer:
inst._serial_writer.write(data)
try:
await inst._serial_writer.drain()
except Exception as e:
logger.warning('send_serial_bytes drain: %s', e)
if not inst:
logger.warning('send_serial_bytes: no instance for client_id=%s', client_id)
return
if not inst._serial_writer:
logger.warning('send_serial_bytes: %s has no serial writer (qemu not connected yet?)', client_id)
return
logger.info('send_serial_bytes: %s sending %d bytes: %r', client_id, len(data), bytes(data[:32]))
inst._serial_writer.write(data)
try:
await inst._serial_writer.drain()
except Exception as e:
logger.warning('send_serial_bytes drain: %s', e)
# ── Boot sequence ─────────────────────────────────────────────────────────

View File

@ -48,6 +48,11 @@ export const PiTerminal: React.FC<PiTerminalProps> = ({ boardId }) => {
} catch (_) {
/* ignore if dimensions not ready */
}
// Without an explicit focus call xterm.js stays passive — onData
// only fires when the DOM element has focus, so users staring at
// a working prompt see no echo because their keystrokes go to
// whatever element had focus at mount time (canvas, code editor).
try { term.focus(); } catch (_) { /* container may not be visible */ }
});
termRef.current = term;