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:
@@ -2,30 +2,27 @@ use std::collections::BTreeMap;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use ely_domain::{BrowserTab, TabId};
|
||||
use gpui::{Bounds, NativeSurfaceHandle, Pixels, Point};
|
||||
|
||||
use crate::services::ProfileDataMode;
|
||||
|
||||
use super::{
|
||||
web_surface_cadence::IDLE_POLL_INTERVAL,
|
||||
web_surface_frame::WebSurfaceFrame,
|
||||
web_surface_geometry::{WebSurfaceClickPoint, WebSurfaceScrollDelta, WebSurfaceSize},
|
||||
web_surface_permissions::WebSurfaceSitePermission,
|
||||
web_surface_runtime::{WebSurfaceRuntime, WebSurfaceRuntimeFrame},
|
||||
web_surface_state::{
|
||||
PerTabSurface, WebSurfaceClickState, WebSurfaceEnsureKey, WebSurfaceInputOutcome,
|
||||
WebSurfaceKeyboardFocusState, WebSurfacePendingInput, WebSurfaceScrollState,
|
||||
WebSurfaceState, WebSurfaceTextInputState, WebSurfaceTickResult,
|
||||
PerTabSurface, WebSurfaceEnsureKey, WebSurfaceKeyboardFocusState, WebSurfacePendingInput,
|
||||
WebSurfaceState, WebSurfaceTickResult,
|
||||
},
|
||||
};
|
||||
|
||||
pub(super) struct WebSurfaceStore {
|
||||
runtime: WebSurfaceRuntime,
|
||||
/// 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
|
||||
/// across the whole window. Lives on the store, not per-tab.
|
||||
keyboard_focus: Option<WebSurfaceKeyboardFocusState>,
|
||||
pub(super) keyboard_focus: Option<WebSurfaceKeyboardFocusState>,
|
||||
}
|
||||
|
||||
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(
|
||||
&mut self,
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user