Show + focus the Servo WebView so it stops dropping every input event

Root cause: Servo's WebView is hidden+unfocused by default. notify_input_event
on a hidden WebView runs paint() hit-test, which returns no hit, and Servo
silently absorbs the event as "already handled". Eleven prior commits all
patched the GPUI side of input forwarding while every event landed in
exactly that black hole.

Fix: webview.show() + webview.focus() immediately after WebViewBuilder::build
in create_webview_in_context, and again in navigate() only on the
should_create_initial_document branch (the load() branch keeps existing
visibility+focus, otherwise a background tab finishing navigation would
steal focus from the foreground tab — Linus correctness ask).

Also unblocks the sidecar binary build, which had been frozen at the
May 9 13:53 stale binary because servo-engine feature was broken on two
fronts:

- ServoHost trait was missing the hover() method that the SoftwareServoHost
  impl declared (regression from "Plug three holes" commit eb58ce7).
- Servo SDK renamed Key::Enter / Backspace / Tab / Escape / Delete /
  Arrow{Up,Down,Left,Right} / Home / End / Page{Up,Down} to
  Key::Named(NamedKey::*). keyboard.rs updated to match.

Sidecar binary rebuilt: 335 MB at May 10 01:44. The earlier 11 commits
were never reaching users because they couldn't recompile the sidecar
without these two upstream-API repairs.
This commit is contained in:
2026-05-10 01:46:39 -04:00
parent 25ff653d83
commit 22ba8517d1
3 changed files with 26 additions and 14 deletions
+2
View File
@@ -318,6 +318,8 @@ pub trait ServoHost {
fn click(&mut self, request: MouseClickRequest) -> Result<(), ServoHostError>; fn click(&mut self, request: MouseClickRequest) -> Result<(), ServoHostError>;
fn hover(&mut self, request: MouseHoverRequest) -> Result<(), ServoHostError>;
fn drag(&mut self, request: MouseDragRequest) -> Result<(), ServoHostError>; fn drag(&mut self, request: MouseDragRequest) -> Result<(), ServoHostError>;
fn touch_tap(&mut self, request: TouchTapRequest) -> Result<(), ServoHostError>; fn touch_tap(&mut self, request: TouchTapRequest) -> Result<(), ServoHostError>;
+14 -14
View File
@@ -1,20 +1,20 @@
use servo::{Code, Key}; use servo::{Code, Key, NamedKey};
pub(crate) fn key_and_code_for_character(character: char) -> (Key, Code) { pub(crate) fn key_and_code_for_character(character: char) -> (Key, Code) {
match character { match character {
'\n' | '\r' => (Key::Enter, Code::Enter), '\n' | '\r' => (Key::Named(NamedKey::Enter), Code::Enter),
'\x08' => (Key::Backspace, Code::Backspace), '\x08' => (Key::Named(NamedKey::Backspace), Code::Backspace),
'\t' => (Key::Tab, Code::Tab), '\t' => (Key::Named(NamedKey::Tab), Code::Tab),
'\x1b' => (Key::Escape, Code::Escape), '\x1b' => (Key::Named(NamedKey::Escape), Code::Escape),
'\x7f' => (Key::Delete, Code::Delete), '\x7f' => (Key::Named(NamedKey::Delete), Code::Delete),
'\u{F700}' => (Key::ArrowUp, Code::ArrowUp), '\u{F700}' => (Key::Named(NamedKey::ArrowUp), Code::ArrowUp),
'\u{F701}' => (Key::ArrowDown, Code::ArrowDown), '\u{F701}' => (Key::Named(NamedKey::ArrowDown), Code::ArrowDown),
'\u{F702}' => (Key::ArrowLeft, Code::ArrowLeft), '\u{F702}' => (Key::Named(NamedKey::ArrowLeft), Code::ArrowLeft),
'\u{F703}' => (Key::ArrowRight, Code::ArrowRight), '\u{F703}' => (Key::Named(NamedKey::ArrowRight), Code::ArrowRight),
'\u{F729}' => (Key::Home, Code::Home), '\u{F729}' => (Key::Named(NamedKey::Home), Code::Home),
'\u{F72B}' => (Key::End, Code::End), '\u{F72B}' => (Key::Named(NamedKey::End), Code::End),
'\u{F72C}' => (Key::PageUp, Code::PageUp), '\u{F72C}' => (Key::Named(NamedKey::PageUp), Code::PageUp),
'\u{F72D}' => (Key::PageDown, Code::PageDown), '\u{F72D}' => (Key::Named(NamedKey::PageDown), Code::PageDown),
_ => (Key::Character(character.to_string()), printable_code(character)), _ => (Key::Character(character.to_string()), printable_code(character)),
} }
} }
+10
View File
@@ -148,6 +148,14 @@ impl ServoHost for SoftwareServoHost {
.delegate(webview.delegate.clone()) .delegate(webview.delegate.clone())
.url(url) .url(url)
.build(); .build();
// Fresh WebView is hidden+unfocused by default; without this
// pair Servo's hit-test silently drops every input event.
// Existing WebViews keep their visibility/focus across loads
// — calling focus() here every navigation would let a
// background tab finishing a load steal focus from the
// foreground tab.
webview.webview.show();
webview.webview.focus();
} else { } else {
webview.webview.load(url); webview.webview.load(url);
} }
@@ -357,6 +365,8 @@ impl SoftwareServoHost {
let webview = WebViewBuilder::new(&self.servo, rendering_context.clone()) let webview = WebViewBuilder::new(&self.servo, rendering_context.clone())
.delegate(delegate.clone()) .delegate(delegate.clone())
.build(); .build();
webview.show();
webview.focus();
self.webviews.insert( self.webviews.insert(
webview_id.clone(), webview_id.clone(),