fix: route keyboard type through text input (#1014)

This commit is contained in:
zhanba
2026-03-25 08:05:20 -07:00
committed by GitHub
parent 5ac01fa743
commit 7d2cd726ec
2 changed files with 54 additions and 18 deletions
+27
View File
@@ -3115,6 +3115,33 @@ async fn handle_keyboard(cmd: &Value, state: &DaemonState) -> Result<Value, Stri
let mgr = state.browser.as_ref().ok_or("Browser not launched")?;
let session_id = mgr.active_session_id()?.to_string();
match cmd.get("subaction").and_then(|v| v.as_str()) {
Some("type") => {
let text = cmd
.get("text")
.and_then(|v| v.as_str())
.ok_or("Missing 'text' parameter")?;
interaction::type_text_into_active_context(&mgr.client, &session_id, text, None)
.await?;
return Ok(json!({ "typed": text }));
}
Some("insertText") => {
let text = cmd
.get("text")
.and_then(|v| v.as_str())
.ok_or("Missing 'text' parameter")?;
mgr.client
.send_command(
"Input.insertText",
Some(json!({ "text": text })),
Some(&session_id),
)
.await?;
return Ok(json!({ "inserted": true }));
}
_ => {}
}
let event_type = cmd
.get("eventType")
.and_then(|v| v.as_str())
+27 -18
View File
@@ -202,25 +202,21 @@ pub async fn type_text(
.await?;
}
type_text_into_active_context(client, session_id, text, delay_ms).await
}
pub async fn type_text_into_active_context(
client: &CdpClient,
session_id: &str,
text: &str,
delay_ms: Option<u64>,
) -> Result<(), String> {
let delay = delay_ms.unwrap_or(0);
for ch in text.chars() {
let text_str = ch.to_string();
let (key, code, key_code) = char_to_key_info(ch);
// Characters that have no US-keyboard mapping (key_code == 0 and empty
// code) are inserted via `Input.insertText`, matching Playwright's
// keyboard.type() fallback behaviour. This handles emoji, CJK, and
// other characters that don't correspond to a physical key.
if key_code == 0 && code.is_empty() {
client
.send_command_typed::<_, Value>(
"Input.insertText",
&InsertTextParams { text: text_str },
Some(session_id),
)
.await?;
} else {
if matches!(ch, '\n' | '\r' | '\t') {
let (key, code, key_code) = char_to_key_info(ch);
let text_str = key_text(&key);
client
.send_command_typed::<_, Value>(
"Input.dispatchKeyEvent",
@@ -228,8 +224,8 @@ pub async fn type_text(
event_type: "keyDown".to_string(),
key: Some(key.clone()),
code: Some(code.clone()),
text: Some(text_str.clone()),
unmodified_text: Some(text_str.clone()),
text: text_str.clone(),
unmodified_text: text_str,
windows_virtual_key_code: Some(key_code),
native_virtual_key_code: Some(key_code),
modifiers: None,
@@ -254,6 +250,19 @@ pub async fn type_text(
Some(session_id),
)
.await?;
} else {
// VS Code/Electron webviews reject repeated dispatchKeyEvent calls
// carrying printable `text`. Insert printable characters directly
// and reserve key events for controls like Enter and Tab.
client
.send_command_typed::<_, Value>(
"Input.insertText",
&InsertTextParams {
text: ch.to_string(),
},
Some(session_id),
)
.await?;
}
if delay > 0 {