refactor(shell): peel input recorders off WebSurfaceStore
`web_surface.rs` had crept to 548 lines; six unrelated input-recorder methods (scroll delta, viewport size, native surface, hover point, click point, typed text) dominated the file. Move them into a sibling `web_surface_input.rs` so the store file (now 338 lines) is the ensure / tick / lifecycle facade and the input file is a flat set of `record_*` methods on the same struct. `surfaces`, `keyboard_focus`, and `surface_mut` become `pub(super)` so the sibling can reach them; everything else stays private.
This commit is contained in:
@@ -32,6 +32,7 @@ mod web_surface_cadence;
|
|||||||
mod web_surface_controller;
|
mod web_surface_controller;
|
||||||
mod web_surface_frame;
|
mod web_surface_frame;
|
||||||
mod web_surface_geometry;
|
mod web_surface_geometry;
|
||||||
|
mod web_surface_input;
|
||||||
mod web_surface_keyboard;
|
mod web_surface_keyboard;
|
||||||
mod web_surface_metadata;
|
mod web_surface_metadata;
|
||||||
mod web_surface_permissions;
|
mod web_surface_permissions;
|
||||||
|
|||||||
@@ -2,30 +2,27 @@ use std::collections::BTreeMap;
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use ely_domain::{BrowserTab, TabId};
|
use ely_domain::{BrowserTab, TabId};
|
||||||
use gpui::{Bounds, NativeSurfaceHandle, Pixels, Point};
|
|
||||||
|
|
||||||
use crate::services::ProfileDataMode;
|
use crate::services::ProfileDataMode;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
web_surface_cadence::IDLE_POLL_INTERVAL,
|
web_surface_cadence::IDLE_POLL_INTERVAL,
|
||||||
web_surface_frame::WebSurfaceFrame,
|
web_surface_frame::WebSurfaceFrame,
|
||||||
web_surface_geometry::{WebSurfaceClickPoint, WebSurfaceScrollDelta, WebSurfaceSize},
|
|
||||||
web_surface_permissions::WebSurfaceSitePermission,
|
web_surface_permissions::WebSurfaceSitePermission,
|
||||||
web_surface_runtime::{WebSurfaceRuntime, WebSurfaceRuntimeFrame},
|
web_surface_runtime::{WebSurfaceRuntime, WebSurfaceRuntimeFrame},
|
||||||
web_surface_state::{
|
web_surface_state::{
|
||||||
PerTabSurface, WebSurfaceClickState, WebSurfaceEnsureKey, WebSurfaceInputOutcome,
|
PerTabSurface, WebSurfaceEnsureKey, WebSurfaceKeyboardFocusState, WebSurfacePendingInput,
|
||||||
WebSurfaceKeyboardFocusState, WebSurfacePendingInput, WebSurfaceScrollState,
|
WebSurfaceState, WebSurfaceTickResult,
|
||||||
WebSurfaceState, WebSurfaceTextInputState, WebSurfaceTickResult,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) struct WebSurfaceStore {
|
pub(super) struct WebSurfaceStore {
|
||||||
runtime: WebSurfaceRuntime,
|
runtime: WebSurfaceRuntime,
|
||||||
/// Single owner of every per-tab invariant. See [`PerTabSurface`].
|
/// Single owner of every per-tab invariant. See [`PerTabSurface`].
|
||||||
surfaces: BTreeMap<TabId, PerTabSurface>,
|
pub(super) surfaces: BTreeMap<TabId, PerTabSurface>,
|
||||||
/// Singleton because only one tab at a time holds keyboard focus
|
/// Singleton because only one tab at a time holds keyboard focus
|
||||||
/// across the whole window. Lives on the store, not per-tab.
|
/// across the whole window. Lives on the store, not per-tab.
|
||||||
keyboard_focus: Option<WebSurfaceKeyboardFocusState>,
|
pub(super) keyboard_focus: Option<WebSurfaceKeyboardFocusState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSurfaceStore {
|
impl WebSurfaceStore {
|
||||||
@@ -207,213 +204,6 @@ impl WebSurfaceStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn record_scroll_delta(
|
|
||||||
&mut self,
|
|
||||||
tab_id: &TabId,
|
|
||||||
requested_url: &str,
|
|
||||||
delta: Point<Pixels>,
|
|
||||||
position: Point<Pixels>,
|
|
||||||
scale_factor: f32,
|
|
||||||
) -> WebSurfaceInputOutcome {
|
|
||||||
let Some(delta) = WebSurfaceScrollDelta::from_point(delta, scale_factor) else {
|
|
||||||
return WebSurfaceInputOutcome::DroppedZeroDelta;
|
|
||||||
};
|
|
||||||
let Some(bounds) = self.surfaces.get(tab_id).and_then(|surface| surface.viewport_bounds)
|
|
||||||
else {
|
|
||||||
return WebSurfaceInputOutcome::DroppedNoViewportBounds;
|
|
||||||
};
|
|
||||||
let Some(point) =
|
|
||||||
WebSurfaceClickPoint::from_window_position(bounds, position, scale_factor)
|
|
||||||
else {
|
|
||||||
return WebSurfaceInputOutcome::DroppedOutOfBounds;
|
|
||||||
};
|
|
||||||
|
|
||||||
let surface = self.surface_mut(tab_id);
|
|
||||||
let flush_throttled = surface.input_flush_is_throttled(Instant::now());
|
|
||||||
let scroll = surface
|
|
||||||
.scroll_offset
|
|
||||||
.get_or_insert_with(|| WebSurfaceScrollState::new(requested_url.to_string()));
|
|
||||||
if scroll.requested_url != requested_url {
|
|
||||||
*scroll = WebSurfaceScrollState::new(requested_url.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
scroll.offset = scroll.offset.scrolled_by(delta);
|
|
||||||
surface.pending_scroll_delta = Some(match surface.pending_scroll_delta {
|
|
||||||
Some(current) => current.combined_with(delta),
|
|
||||||
None => delta,
|
|
||||||
});
|
|
||||||
surface.pending_scroll_point = Some(point);
|
|
||||||
surface.mark_pending_input_started();
|
|
||||||
surface.click_point = None;
|
|
||||||
if flush_throttled {
|
|
||||||
WebSurfaceInputOutcome::Buffered
|
|
||||||
} else {
|
|
||||||
WebSurfaceInputOutcome::Applied
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn record_viewport_size(
|
|
||||||
&mut self,
|
|
||||||
tab_id: &TabId,
|
|
||||||
bounds: Bounds<Pixels>,
|
|
||||||
scale_factor: f32,
|
|
||||||
) -> WebSurfaceInputOutcome {
|
|
||||||
let Some(size) = WebSurfaceSize::from_bounds(bounds, scale_factor) else {
|
|
||||||
return WebSurfaceInputOutcome::DroppedInvalidBounds;
|
|
||||||
};
|
|
||||||
let surface = self.surface_mut(tab_id);
|
|
||||||
surface.viewport_bounds = Some(bounds);
|
|
||||||
|
|
||||||
let Some(current_size) = surface.viewport_size else {
|
|
||||||
surface.viewport_size = Some(size);
|
|
||||||
return WebSurfaceInputOutcome::Applied;
|
|
||||||
};
|
|
||||||
|
|
||||||
if current_size == size {
|
|
||||||
return WebSurfaceInputOutcome::NoChange;
|
|
||||||
}
|
|
||||||
|
|
||||||
surface.viewport_size = Some(size);
|
|
||||||
WebSurfaceInputOutcome::Applied
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn record_native_surface(
|
|
||||||
&mut self,
|
|
||||||
tab_id: &TabId,
|
|
||||||
native_surface: NativeSurfaceHandle,
|
|
||||||
) -> WebSurfaceInputOutcome {
|
|
||||||
let surface = self.surface_mut(tab_id);
|
|
||||||
if surface
|
|
||||||
.native_surface
|
|
||||||
.as_ref()
|
|
||||||
.is_some_and(|current| current.identity() == native_surface.identity())
|
|
||||||
{
|
|
||||||
return WebSurfaceInputOutcome::NoChange;
|
|
||||||
}
|
|
||||||
surface.native_surface = Some(native_surface);
|
|
||||||
surface.last_ensure_key = None;
|
|
||||||
WebSurfaceInputOutcome::Applied
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn record_hover_point(
|
|
||||||
&mut self,
|
|
||||||
tab_id: &TabId,
|
|
||||||
position: Point<Pixels>,
|
|
||||||
scale_factor: f32,
|
|
||||||
) -> WebSurfaceInputOutcome {
|
|
||||||
self.record_hover_point_at(tab_id, position, scale_factor, Instant::now())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn record_hover_point_at(
|
|
||||||
&mut self,
|
|
||||||
tab_id: &TabId,
|
|
||||||
position: Point<Pixels>,
|
|
||||||
scale_factor: f32,
|
|
||||||
now: Instant,
|
|
||||||
) -> WebSurfaceInputOutcome {
|
|
||||||
let Some(surface) = self.surfaces.get_mut(tab_id) else {
|
|
||||||
return WebSurfaceInputOutcome::DroppedNoViewportBounds;
|
|
||||||
};
|
|
||||||
let Some(bounds) = surface.viewport_bounds else {
|
|
||||||
return WebSurfaceInputOutcome::DroppedNoViewportBounds;
|
|
||||||
};
|
|
||||||
let Some(point) =
|
|
||||||
WebSurfaceClickPoint::from_window_position(bounds, position, scale_factor)
|
|
||||||
else {
|
|
||||||
return WebSurfaceInputOutcome::DroppedOutOfBounds;
|
|
||||||
};
|
|
||||||
if surface.hover_point == Some(point) {
|
|
||||||
return WebSurfaceInputOutcome::NoChange;
|
|
||||||
}
|
|
||||||
if surface.hover_is_throttled(now) {
|
|
||||||
return WebSurfaceInputOutcome::NoChange;
|
|
||||||
}
|
|
||||||
surface.hover_point = Some(point);
|
|
||||||
surface.mark_hover_enqueued(now);
|
|
||||||
WebSurfaceInputOutcome::Applied
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn record_click_point(
|
|
||||||
&mut self,
|
|
||||||
tab_id: &TabId,
|
|
||||||
requested_url: &str,
|
|
||||||
position: Point<Pixels>,
|
|
||||||
scale_factor: f32,
|
|
||||||
) -> WebSurfaceInputOutcome {
|
|
||||||
let Some(bounds) = self.surfaces.get(tab_id).and_then(|surface| surface.viewport_bounds)
|
|
||||||
else {
|
|
||||||
return WebSurfaceInputOutcome::DroppedNoViewportBounds;
|
|
||||||
};
|
|
||||||
let Some(point) =
|
|
||||||
WebSurfaceClickPoint::from_window_position(bounds, position, scale_factor)
|
|
||||||
else {
|
|
||||||
return WebSurfaceInputOutcome::DroppedOutOfBounds;
|
|
||||||
};
|
|
||||||
|
|
||||||
let scroll_offset = self
|
|
||||||
.surfaces
|
|
||||||
.get(tab_id)
|
|
||||||
.map(|surface| surface.scroll_offset_for(requested_url))
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
let state =
|
|
||||||
WebSurfaceClickState { requested_url: requested_url.to_string(), scroll_offset, point };
|
|
||||||
self.keyboard_focus = Some(WebSurfaceKeyboardFocusState {
|
|
||||||
tab_id: tab_id.clone(),
|
|
||||||
requested_url: requested_url.to_string(),
|
|
||||||
scroll_offset: state.scroll_offset,
|
|
||||||
click_point: state.point,
|
|
||||||
});
|
|
||||||
let surface = self.surface_mut(tab_id);
|
|
||||||
surface.typed_text = None;
|
|
||||||
surface.click_point = Some(state);
|
|
||||||
surface.mark_pending_input_started();
|
|
||||||
WebSurfaceInputOutcome::Applied
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn record_typed_text(
|
|
||||||
&mut self,
|
|
||||||
tab_id: &TabId,
|
|
||||||
requested_url: &str,
|
|
||||||
text: &str,
|
|
||||||
) -> WebSurfaceInputOutcome {
|
|
||||||
if text.is_empty() {
|
|
||||||
return WebSurfaceInputOutcome::DroppedEmptyText;
|
|
||||||
}
|
|
||||||
let Some(focus) = self.keyboard_focus.as_ref() else {
|
|
||||||
return WebSurfaceInputOutcome::DroppedNoKeyboardFocus;
|
|
||||||
};
|
|
||||||
if focus.tab_id != *tab_id || focus.requested_url != requested_url {
|
|
||||||
return WebSurfaceInputOutcome::DroppedFocusMismatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
let scroll_offset = focus.scroll_offset;
|
|
||||||
let click_point = focus.click_point;
|
|
||||||
let surface = self.surface_mut(tab_id);
|
|
||||||
|
|
||||||
let entry = surface.typed_text.get_or_insert_with(|| WebSurfaceTextInputState {
|
|
||||||
requested_url: requested_url.to_string(),
|
|
||||||
scroll_offset,
|
|
||||||
click_point,
|
|
||||||
text: String::new(),
|
|
||||||
});
|
|
||||||
if entry.requested_url != requested_url
|
|
||||||
|| entry.scroll_offset != scroll_offset
|
|
||||||
|| entry.click_point != click_point
|
|
||||||
{
|
|
||||||
*entry = WebSurfaceTextInputState {
|
|
||||||
requested_url: requested_url.to_string(),
|
|
||||||
scroll_offset,
|
|
||||||
click_point,
|
|
||||||
text: String::new(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
entry.text.push_str(text);
|
|
||||||
surface.mark_pending_input_started();
|
|
||||||
WebSurfaceInputOutcome::Applied
|
|
||||||
}
|
|
||||||
|
|
||||||
fn take_pending_input(
|
fn take_pending_input(
|
||||||
&mut self,
|
&mut self,
|
||||||
tab_id: &TabId,
|
tab_id: &TabId,
|
||||||
@@ -512,7 +302,7 @@ impl WebSurfaceStore {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn surface_mut(&mut self, tab_id: &TabId) -> &mut PerTabSurface {
|
pub(super) fn surface_mut(&mut self, tab_id: &TabId) -> &mut PerTabSurface {
|
||||||
self.surfaces.entry(tab_id.clone()).or_insert_with(PerTabSurface::new)
|
self.surfaces.entry(tab_id.clone()).or_insert_with(PerTabSurface::new)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,222 @@
|
|||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use ely_domain::TabId;
|
||||||
|
use gpui::{Bounds, NativeSurfaceHandle, Pixels, Point};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
web_surface::WebSurfaceStore,
|
||||||
|
web_surface_geometry::{WebSurfaceClickPoint, WebSurfaceScrollDelta, WebSurfaceSize},
|
||||||
|
web_surface_state::{
|
||||||
|
WebSurfaceClickState, WebSurfaceInputOutcome, WebSurfaceKeyboardFocusState,
|
||||||
|
WebSurfaceScrollState, WebSurfaceTextInputState,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl WebSurfaceStore {
|
||||||
|
pub(super) fn record_scroll_delta(
|
||||||
|
&mut self,
|
||||||
|
tab_id: &TabId,
|
||||||
|
requested_url: &str,
|
||||||
|
delta: Point<Pixels>,
|
||||||
|
position: Point<Pixels>,
|
||||||
|
scale_factor: f32,
|
||||||
|
) -> WebSurfaceInputOutcome {
|
||||||
|
let Some(delta) = WebSurfaceScrollDelta::from_point(delta, scale_factor) else {
|
||||||
|
return WebSurfaceInputOutcome::DroppedZeroDelta;
|
||||||
|
};
|
||||||
|
let Some(bounds) = self.surfaces.get(tab_id).and_then(|surface| surface.viewport_bounds)
|
||||||
|
else {
|
||||||
|
return WebSurfaceInputOutcome::DroppedNoViewportBounds;
|
||||||
|
};
|
||||||
|
let Some(point) =
|
||||||
|
WebSurfaceClickPoint::from_window_position(bounds, position, scale_factor)
|
||||||
|
else {
|
||||||
|
return WebSurfaceInputOutcome::DroppedOutOfBounds;
|
||||||
|
};
|
||||||
|
|
||||||
|
let surface = self.surface_mut(tab_id);
|
||||||
|
let flush_throttled = surface.input_flush_is_throttled(Instant::now());
|
||||||
|
let scroll = surface
|
||||||
|
.scroll_offset
|
||||||
|
.get_or_insert_with(|| WebSurfaceScrollState::new(requested_url.to_string()));
|
||||||
|
if scroll.requested_url != requested_url {
|
||||||
|
*scroll = WebSurfaceScrollState::new(requested_url.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
scroll.offset = scroll.offset.scrolled_by(delta);
|
||||||
|
surface.pending_scroll_delta = Some(match surface.pending_scroll_delta {
|
||||||
|
Some(current) => current.combined_with(delta),
|
||||||
|
None => delta,
|
||||||
|
});
|
||||||
|
surface.pending_scroll_point = Some(point);
|
||||||
|
surface.mark_pending_input_started();
|
||||||
|
surface.click_point = None;
|
||||||
|
if flush_throttled {
|
||||||
|
WebSurfaceInputOutcome::Buffered
|
||||||
|
} else {
|
||||||
|
WebSurfaceInputOutcome::Applied
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn record_viewport_size(
|
||||||
|
&mut self,
|
||||||
|
tab_id: &TabId,
|
||||||
|
bounds: Bounds<Pixels>,
|
||||||
|
scale_factor: f32,
|
||||||
|
) -> WebSurfaceInputOutcome {
|
||||||
|
let Some(size) = WebSurfaceSize::from_bounds(bounds, scale_factor) else {
|
||||||
|
return WebSurfaceInputOutcome::DroppedInvalidBounds;
|
||||||
|
};
|
||||||
|
let surface = self.surface_mut(tab_id);
|
||||||
|
surface.viewport_bounds = Some(bounds);
|
||||||
|
|
||||||
|
let Some(current_size) = surface.viewport_size else {
|
||||||
|
surface.viewport_size = Some(size);
|
||||||
|
return WebSurfaceInputOutcome::Applied;
|
||||||
|
};
|
||||||
|
|
||||||
|
if current_size == size {
|
||||||
|
return WebSurfaceInputOutcome::NoChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
surface.viewport_size = Some(size);
|
||||||
|
WebSurfaceInputOutcome::Applied
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn record_native_surface(
|
||||||
|
&mut self,
|
||||||
|
tab_id: &TabId,
|
||||||
|
native_surface: NativeSurfaceHandle,
|
||||||
|
) -> WebSurfaceInputOutcome {
|
||||||
|
let surface = self.surface_mut(tab_id);
|
||||||
|
if surface
|
||||||
|
.native_surface
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|current| current.identity() == native_surface.identity())
|
||||||
|
{
|
||||||
|
return WebSurfaceInputOutcome::NoChange;
|
||||||
|
}
|
||||||
|
surface.native_surface = Some(native_surface);
|
||||||
|
surface.last_ensure_key = None;
|
||||||
|
WebSurfaceInputOutcome::Applied
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn record_hover_point(
|
||||||
|
&mut self,
|
||||||
|
tab_id: &TabId,
|
||||||
|
position: Point<Pixels>,
|
||||||
|
scale_factor: f32,
|
||||||
|
) -> WebSurfaceInputOutcome {
|
||||||
|
self.record_hover_point_at(tab_id, position, scale_factor, Instant::now())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn record_hover_point_at(
|
||||||
|
&mut self,
|
||||||
|
tab_id: &TabId,
|
||||||
|
position: Point<Pixels>,
|
||||||
|
scale_factor: f32,
|
||||||
|
now: Instant,
|
||||||
|
) -> WebSurfaceInputOutcome {
|
||||||
|
let Some(surface) = self.surfaces.get_mut(tab_id) else {
|
||||||
|
return WebSurfaceInputOutcome::DroppedNoViewportBounds;
|
||||||
|
};
|
||||||
|
let Some(bounds) = surface.viewport_bounds else {
|
||||||
|
return WebSurfaceInputOutcome::DroppedNoViewportBounds;
|
||||||
|
};
|
||||||
|
let Some(point) =
|
||||||
|
WebSurfaceClickPoint::from_window_position(bounds, position, scale_factor)
|
||||||
|
else {
|
||||||
|
return WebSurfaceInputOutcome::DroppedOutOfBounds;
|
||||||
|
};
|
||||||
|
if surface.hover_point == Some(point) {
|
||||||
|
return WebSurfaceInputOutcome::NoChange;
|
||||||
|
}
|
||||||
|
if surface.hover_is_throttled(now) {
|
||||||
|
return WebSurfaceInputOutcome::NoChange;
|
||||||
|
}
|
||||||
|
surface.hover_point = Some(point);
|
||||||
|
surface.mark_hover_enqueued(now);
|
||||||
|
WebSurfaceInputOutcome::Applied
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn record_click_point(
|
||||||
|
&mut self,
|
||||||
|
tab_id: &TabId,
|
||||||
|
requested_url: &str,
|
||||||
|
position: Point<Pixels>,
|
||||||
|
scale_factor: f32,
|
||||||
|
) -> WebSurfaceInputOutcome {
|
||||||
|
let Some(bounds) = self.surfaces.get(tab_id).and_then(|surface| surface.viewport_bounds)
|
||||||
|
else {
|
||||||
|
return WebSurfaceInputOutcome::DroppedNoViewportBounds;
|
||||||
|
};
|
||||||
|
let Some(point) =
|
||||||
|
WebSurfaceClickPoint::from_window_position(bounds, position, scale_factor)
|
||||||
|
else {
|
||||||
|
return WebSurfaceInputOutcome::DroppedOutOfBounds;
|
||||||
|
};
|
||||||
|
|
||||||
|
let scroll_offset = self
|
||||||
|
.surfaces
|
||||||
|
.get(tab_id)
|
||||||
|
.map(|surface| surface.scroll_offset_for(requested_url))
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let state =
|
||||||
|
WebSurfaceClickState { requested_url: requested_url.to_string(), scroll_offset, point };
|
||||||
|
self.keyboard_focus = Some(WebSurfaceKeyboardFocusState {
|
||||||
|
tab_id: tab_id.clone(),
|
||||||
|
requested_url: requested_url.to_string(),
|
||||||
|
scroll_offset: state.scroll_offset,
|
||||||
|
click_point: state.point,
|
||||||
|
});
|
||||||
|
let surface = self.surface_mut(tab_id);
|
||||||
|
surface.typed_text = None;
|
||||||
|
surface.click_point = Some(state);
|
||||||
|
surface.mark_pending_input_started();
|
||||||
|
WebSurfaceInputOutcome::Applied
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn record_typed_text(
|
||||||
|
&mut self,
|
||||||
|
tab_id: &TabId,
|
||||||
|
requested_url: &str,
|
||||||
|
text: &str,
|
||||||
|
) -> WebSurfaceInputOutcome {
|
||||||
|
if text.is_empty() {
|
||||||
|
return WebSurfaceInputOutcome::DroppedEmptyText;
|
||||||
|
}
|
||||||
|
let Some(focus) = self.keyboard_focus.as_ref() else {
|
||||||
|
return WebSurfaceInputOutcome::DroppedNoKeyboardFocus;
|
||||||
|
};
|
||||||
|
if focus.tab_id != *tab_id || focus.requested_url != requested_url {
|
||||||
|
return WebSurfaceInputOutcome::DroppedFocusMismatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
let scroll_offset = focus.scroll_offset;
|
||||||
|
let click_point = focus.click_point;
|
||||||
|
let surface = self.surface_mut(tab_id);
|
||||||
|
|
||||||
|
let entry = surface.typed_text.get_or_insert_with(|| WebSurfaceTextInputState {
|
||||||
|
requested_url: requested_url.to_string(),
|
||||||
|
scroll_offset,
|
||||||
|
click_point,
|
||||||
|
text: String::new(),
|
||||||
|
});
|
||||||
|
if entry.requested_url != requested_url
|
||||||
|
|| entry.scroll_offset != scroll_offset
|
||||||
|
|| entry.click_point != click_point
|
||||||
|
{
|
||||||
|
*entry = WebSurfaceTextInputState {
|
||||||
|
requested_url: requested_url.to_string(),
|
||||||
|
scroll_offset,
|
||||||
|
click_point,
|
||||||
|
text: String::new(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.text.push_str(text);
|
||||||
|
surface.mark_pending_input_started();
|
||||||
|
WebSurfaceInputOutcome::Applied
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user