Plug three holes in Servo input forwarding
1. Scroll no longer wipes keyboard focus. Servo holds DOM focus across wheel events; the shell was clearing keyboard_focus and typed_texts on every scroll, so a focused input went deaf the moment the user scrolled. Scroll still drops the buffered click point because that coordinate is captured against the pre-scroll viewport. 2. Mouse-down hands focus to the shell's root focus handle (in addition to mouse-up's existing click forwarding). The user can now start typing the moment they press the page, instead of having to first complete a click round-trip to escape the omnibar's focus. 3. Sidecar hover() honors the requesting webview_id instead of defaulting to the first webview in the map, so multi-tab sidecars no longer pipe every hover into tab #1.
This commit is contained in:
@@ -137,9 +137,13 @@ impl WebSurfaceStore {
|
||||
.entry(tab_id.clone())
|
||||
.and_modify(|current| *current = current.combined_with(delta))
|
||||
.or_insert(delta);
|
||||
// Drop any buffered click — its viewport coordinates were
|
||||
// captured against the pre-scroll page, so applying it after
|
||||
// the scroll would land on the wrong DOM element. Keep
|
||||
// `keyboard_focus` and `typed_texts` though: Servo maintains
|
||||
// its own DOM focus across scrolls, so a focused input keeps
|
||||
// accepting the user's keystrokes after they wheel-scroll.
|
||||
self.click_points.remove(tab_id);
|
||||
self.typed_texts.remove(tab_id);
|
||||
self.keyboard_focus = None;
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,14 @@ impl ElyShell {
|
||||
}
|
||||
}
|
||||
|
||||
/// Hand focus to the shell's root focus handle so subsequent
|
||||
/// keystrokes route to the web surface. Called on the very first
|
||||
/// mouse-down inside an external page so the user can start
|
||||
/// typing without waiting for the click to fully resolve.
|
||||
pub(super) fn focus_web_surface(&self, window: &mut gpui::Window) {
|
||||
self.focus_handle.focus(window);
|
||||
}
|
||||
|
||||
pub(super) fn type_text_in_external_web_viewport(
|
||||
&mut self,
|
||||
tab_id: TabId,
|
||||
|
||||
@@ -90,6 +90,7 @@ fn render_input_overlay(
|
||||
url: String,
|
||||
state_entity: Entity<ElyShell>,
|
||||
) -> impl IntoElement {
|
||||
let down_entity = state_entity.clone();
|
||||
let click_tab_id = tab_id.clone();
|
||||
let click_url = url.clone();
|
||||
let click_entity = state_entity.clone();
|
||||
@@ -103,6 +104,16 @@ fn render_input_overlay(
|
||||
.absolute()
|
||||
.size_full()
|
||||
.occlude()
|
||||
// Mouse-down hands focus to the shell's root focus handle so
|
||||
// subsequent keystrokes route to the web surface instead of
|
||||
// the omnibar Input. Doing this on mouse-down (not mouse-up)
|
||||
// lets the user start typing as soon as they press, matching
|
||||
// native browser focus semantics.
|
||||
.on_mouse_down(MouseButton::Left, move |_event, window, cx| {
|
||||
down_entity.update(cx, |shell, _cx| {
|
||||
shell.focus_web_surface(window);
|
||||
});
|
||||
})
|
||||
.capture_any_mouse_up(move |event, window, cx| {
|
||||
if event.button != MouseButton::Left {
|
||||
return;
|
||||
|
||||
@@ -9,9 +9,9 @@ use std::{
|
||||
|
||||
use ely_domain::{DEFAULT_ZOOM_PERCENT, ProfileId, TabId, UrlText};
|
||||
use ely_servo_host::{
|
||||
KeyboardTextRequest, MouseClickRequest, NavigationRequest, PageZoomRequest, PermissionDecision,
|
||||
PermissionRequest, RenderedFrame, ResizeRequest, ScrollRequest, ServoHost, ServoHostError,
|
||||
ServoSurfaceSize, SoftwareServoHost, WebViewSnapshot, WebViewState,
|
||||
KeyboardTextRequest, MouseClickRequest, MouseHoverRequest, NavigationRequest, PageZoomRequest,
|
||||
PermissionDecision, PermissionRequest, RenderedFrame, ResizeRequest, ScrollRequest, ServoHost,
|
||||
ServoHostError, ServoSurfaceSize, SoftwareServoHost, WebViewSnapshot, WebViewState,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
@@ -230,7 +230,7 @@ fn apply_input(
|
||||
}
|
||||
|
||||
if let (Some(x), Some(y)) = (hover_x, hover_y) {
|
||||
host.hover(x, y)?;
|
||||
host.hover(MouseHoverRequest { webview_id: session.webview_id.clone(), x, y })?;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -242,6 +242,13 @@ pub struct MouseClickRequest {
|
||||
pub y: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct MouseHoverRequest {
|
||||
pub webview_id: WebViewId,
|
||||
pub x: u32,
|
||||
pub y: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct MouseDragRequest {
|
||||
pub webview_id: WebViewId,
|
||||
|
||||
@@ -15,9 +15,10 @@ mod runtime_webview;
|
||||
|
||||
pub use error::ServoHostError;
|
||||
pub use host::{
|
||||
KeyboardTextRequest, MouseClickRequest, MouseDragRequest, NavigationRequest, PageZoomRequest,
|
||||
PermissionDecision, PermissionRequest, RenderedFrame, RenderedFrameSummary, ResizeRequest,
|
||||
ScreenshotRequest, ScrollRequest, ServoHost, TouchTapRequest, WebViewSnapshot, WebViewState,
|
||||
KeyboardTextRequest, MouseClickRequest, MouseDragRequest, MouseHoverRequest,
|
||||
NavigationRequest, PageZoomRequest, PermissionDecision, PermissionRequest, RenderedFrame,
|
||||
RenderedFrameSummary, ResizeRequest, ScreenshotRequest, ScrollRequest, ServoHost,
|
||||
TouchTapRequest, WebViewSnapshot, WebViewState,
|
||||
};
|
||||
#[cfg(feature = "servo-engine")]
|
||||
pub use runtime::{ServoSurfaceSize, SoftwareServoHost};
|
||||
|
||||
@@ -20,9 +20,10 @@ use servo::{
|
||||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
KeyboardTextRequest, MouseClickRequest, MouseDragRequest, NavigationRequest, PageZoomRequest,
|
||||
PermissionDecision, PermissionRequest, RenderedFrame, ResizeRequest, ScreenshotRequest,
|
||||
ScrollRequest, ServoHost, ServoHostError, TouchTapRequest, WebViewSnapshot, WebViewState,
|
||||
KeyboardTextRequest, MouseClickRequest, MouseDragRequest, MouseHoverRequest,
|
||||
NavigationRequest, PageZoomRequest, PermissionDecision, PermissionRequest, RenderedFrame,
|
||||
ResizeRequest, ScreenshotRequest, ScrollRequest, ServoHost, ServoHostError, TouchTapRequest,
|
||||
WebViewSnapshot, WebViewState,
|
||||
runtime_input::{
|
||||
send_keyboard_text, send_mouse_click, send_mouse_drag, send_mouse_hover, send_touch_tap,
|
||||
},
|
||||
@@ -196,10 +197,13 @@ impl ServoHost for SoftwareServoHost {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn hover(&mut self, x: u32, y: u32) -> Result<(), ServoHostError> {
|
||||
if let Some(webview) = self.webviews.values().next() {
|
||||
send_mouse_hover(&webview.webview, x, y);
|
||||
}
|
||||
fn hover(&mut self, request: MouseHoverRequest) -> Result<(), ServoHostError> {
|
||||
let webview = self
|
||||
.webviews
|
||||
.get(&request.webview_id)
|
||||
.ok_or_else(|| ServoHostError::WebViewNotFound { id: request.webview_id.clone() })?;
|
||||
|
||||
send_mouse_hover(&webview.webview, request.x, request.y);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user