Skip to content

feat(panel): hardware buttons, keyboard, and idle-freeze fix for the portable emulator panel - #24

Merged
dev-josias merged 3 commits into
mainfrom
feat/portable-panel-hardware-keys
Jul 1, 2026
Merged

feat(panel): hardware buttons, keyboard, and idle-freeze fix for the portable emulator panel#24
dev-josias merged 3 commits into
mainfrom
feat/portable-panel-hardware-keys

Conversation

@dev-josias

@dev-josias dev-josias commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

What

Brings the portable Windows/Linux Android emulator panel to input parity with the macOS sidebar (hardware buttons + keyboard) and fixes a panel-freeze bug, all over the existing gRPC connection (no adb shell).

1. Hardware buttons

Home / Back / Recents / Power in the panel sidebar (🏠 ◀ ⊞ ⏻), forwarded via EmulatorInput::key ("GoHome"/"GoBack"/"AppSwitch"/"Power").

2. Keyboard

The video_frame is now focusable; KeyDown events map floem keys (characters + Enter/Backspace/Tab/Esc/Delete/arrows) to EmulatorInput::key, so clicking into the panel routes typing to the device.

3. Fix send_key (the fix that makes keys actually work)

send_key sent a lone keypress, which the emulator ignores for non-character keys (Home/Back/…) — the same way the DOM only fires keypress for character keys. Now it sends a proper keydown + keyup pair. (The macOS panel dodged this by shelling out to adb; the portable panel uses gRPC, so the event type matters.) This is why keys never reached the device before.

4. Fix panel freeze on an idle screen (emulator_stream.rs)

The emulator emits a frame only when the screen changes, so an idle screen produces none. The 10s "no-frame" watchdog (from #22) treated that as a dead socket and stopped the stream permanently → the panel froze on the last frame until a manual Stop→Start, which read as "taps/swiping stopped working" (input still reached the device; nothing repainted). Now the stream reconnects on a stall/end instead of giving up (a fresh stream repaints the current frame immediately); it only exits when the panel closes. Timeout 10s→20s to cut idle churn; native-resolution probe cached across reconnects.

Verified live on Windows (real Pixel_9a, headless -gpu host)

  • Hardware buttons — pressing Home from the app drawer returns to the home screen (also proves the send_key keydown+keyup fix).
  • Freeze fix — left the panel idle 25s: log shows no frame for 20s, reconnecting (not stopping) and the on-screen clock keeps advancing; a swipe afterward navigates the device. Stream stays live, touch works.
  • ✅ Build green; cargo fmt clean (CI confirms Clippy/build on all three OSes).

Not independently confirmed (low risk)

  • Keyboard text typing wasn't visually confirmed end-to-end — driving a device-side text field via screenshot automation was finicky. It rides the same verified send_key path + focusable, so it should work; worth a 2-second manual check (click into the panel, focus a device text field, type).

Note

Item 4 touches emulator_stream.rs (the #22 watchdog area) — heads-up if that's being iterated on elsewhere.

🤖 Generated with Claude Code

Bring the Windows/Linux panel to input parity with the macOS sidebar, all over
the existing gRPC connection (no adb shell):

- Hardware buttons (Home/Back/Recents/Power) in the sidebar, forwarded via
  EmulatorInput::key ("GoHome"/"GoBack"/"AppSwitch"/"Power"). Verified live on
  Windows: pressing Home from the app drawer returns to the home screen.
- Keyboard: the video_frame is `focusable`, and KeyDown events map floem keys
  (characters + Enter/Backspace/Tab/Esc/Delete/arrows) to EmulatorInput::key, so
  clicking into the panel routes typing to the device.
- Fix EmulatorGrpcClient::send_key: send a keydown+keyup pair instead of a lone
  `keypress`, which the emulator ignores for non-character keys (Home/Back/…) —
  this is why keys never reached the device before (the macOS panel sidesteps it
  by shelling out to `adb`). This is the fix that makes the buttons actually work.
… screen

The emulator emits a screenshot frame only when the screen *changes*, so an idle
screen legitimately produces none. The 10s "no frame" watchdog treated that as a
dead socket and stopped the stream for good — the panel froze (last frame stuck)
until a manual Stop→Start, which read as "taps/swiping stopped working" (input
still reached the device, but nothing repainted).

Wrap connect+stream in a reconnect loop: on a stall/end, drop the stream and
reconnect (a fresh stream repaints the current frame immediately), only exiting
when the panel (UI receiver) is gone. Timeout bumped 10s→20s to cut idle churn.
Native-resolution probe is cached across reconnects.
@dev-josias dev-josias changed the title feat(panel): hardware buttons + keyboard for the portable emulator panel feat(panel): hardware buttons, keyboard, and idle-freeze fix for the portable emulator panel Jul 1, 2026
@dev-josias
dev-josias merged commit 904d13f into main Jul 1, 2026
7 checks passed
dev-josias added a commit that referenced this pull request Jul 1, 2026
* docs: record agent-CLI backends + emulator hardware keys/keyboard

Reflect what landed on main toward v0.3.0:
- AI assistant now supports external agent CLIs — Claude Code (per-action
  approval), Codex (sandboxed + consent, macOS/Linux), Gemini (read-only)
  — PR #25. Added to README features, the Pages feature grid, and the
  CLAUDE.md status/positioning.
- Emulator panel gained hardware buttons (Home/Back/Power) + keyboard and
  an idle-freeze fix (PR #24/#26); updated the preview wording everywhere.

Download badge stays 0.2.0 until a v0.3.0 tag is cut (per CLAUDE.md).

* docs(site): next-level landing page redesign

Rebuilt the GitHub Pages landing page for impact + conversion:
- Animated aurora backdrop, glassmorphism nav pill, gradient hero
  headline, and an OS-detected primary CTA ("Download for macOS/
  Windows/Linux" via navigator).
- Product screenshot framed in a floating app-window with a gradient
  glow border + thumbnail switcher.
- Trust/stats strip, bento feature grid with hover glow, and a new
  AI-agents spotlight with a live mock terminal + approval card that
  shows the actual Claude Code per-action approval flow.
- Scroll-reveal animations (IntersectionObserver), smooth scroll,
  prefers-reduced-motion + responsive/mobile fallbacks.
- Verified in-browser: renders clean, no console errors, reveals +
  OS-detection working. Download badge stays v0.2.0 until the tag.

Content-only (no code); real download/GitHub links + screenshots +
Lapce attribution + Apache-2.0 all preserved.

* docs(site): reskin landing page in UMIDE's own theme colors

Swap the generic blue/violet palette for UMIDE's actual identity:
- One Dark base #282c34 (the editor background) with a subtle depth
  gradient from the secondary bg #21252b.
- Brand blue from the logo (#3da4eb / #196eae) + theme blue #61afef as
  the primary accent and hero/CTA gradient (blue → cyan #56b6c2).
- Theme purple #c678dd and cyan for the aurora + secondary accents;
  theme green #98c379 for the 'live' pip.
The page now visually matches the app it ships.

* docs(site): add 'See it in action' demo-video section + lightbox

A dedicated demo section with a dimmed product poster, a pulsing gradient
play button, and a responsive video lightbox (YouTube iframe or inline
mp4). Publishing the demo is a one-line change: set the DEMO_VIDEO JS
constant to a YouTube ID or an mp4 path and commit. Until then the play
button gracefully links to the repo. Also adds a 'Demo' nav link.

Verified in-browser: poster + play button render, lightbox opens/embeds/
closes (× · backdrop · Esc) and clears its slot, no console errors.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant