Fold WebSurfaceStore into a single PerTabSurface owner
Eleven parallel BTreeMaps (click_points, hover_points, pending_scroll_deltas, scroll_offsets, typed_texts, viewport_bounds, viewport_sizes, pending_viewport_sizes, states, etc.) made every input bug a coordination problem across 11 disjoint maps with no compile-time guarantee they stayed in sync. Collapse them into BTreeMap<TabId, PerTabSurface>: one owner per tab, one lookup per input event. keyboard_focus stays at the store level because only one tab in the window can hold focus at a time. Public API and behavior are unchanged; the previously-fixed "scroll keeps keyboard_focus" semantics are preserved. cargo test ely_browser_core + cargo test ely_app --bin ely_app green.
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
use ely_domain::TabId;
|
||||
use gpui::{Bounds, Pixels};
|
||||
|
||||
use super::{
|
||||
web_surface_frame::WebSurfaceFrame,
|
||||
web_surface_geometry::{WebSurfaceClickPoint, WebSurfaceScrollOffset},
|
||||
web_surface_geometry::{
|
||||
WebSurfaceClickPoint, WebSurfaceScrollDelta, WebSurfaceScrollOffset, WebSurfaceSize,
|
||||
},
|
||||
};
|
||||
|
||||
pub(super) struct WebSurfaceScrollState {
|
||||
@@ -41,7 +44,7 @@ pub(super) struct WebSurfaceTextInputState {
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub(super) struct WebSurfacePendingInput {
|
||||
pub(super) scroll_offset: WebSurfaceScrollOffset,
|
||||
pub(super) scroll_delta: Option<super::web_surface_geometry::WebSurfaceScrollDelta>,
|
||||
pub(super) scroll_delta: Option<WebSurfaceScrollDelta>,
|
||||
pub(super) click_point: Option<WebSurfaceClickPoint>,
|
||||
pub(super) hover_point: Option<WebSurfaceClickPoint>,
|
||||
pub(super) typed_text: Option<String>,
|
||||
@@ -52,3 +55,52 @@ pub(super) enum WebSurfaceState {
|
||||
Ready(WebSurfaceFrame),
|
||||
Failed { message: String },
|
||||
}
|
||||
|
||||
/// All per-tab surface invariants in one owner.
|
||||
///
|
||||
/// Replaces the previous 11 parallel `BTreeMap<TabId, _>` fields on
|
||||
/// `WebSurfaceStore`. Every per-tab field lives here so a single
|
||||
/// lookup yields the full input/render context for that tab; the
|
||||
/// remaining cross-tab state (the runtime backend and the singular
|
||||
/// `keyboard_focus` pointer to the active tab) stays on the store.
|
||||
///
|
||||
/// All inputs that depend on a measured viewport take their
|
||||
/// pre-conditions from this struct (`viewport_bounds`,
|
||||
/// `viewport_size`), so "viewport not ready" turns into a guard at
|
||||
/// the call site instead of a `get` on a parallel map that may or
|
||||
/// may not be populated.
|
||||
pub(super) struct PerTabSurface {
|
||||
pub(super) viewport_bounds: Option<Bounds<Pixels>>,
|
||||
pub(super) viewport_size: Option<WebSurfaceSize>,
|
||||
pub(super) pending_viewport_size: Option<WebSurfaceSize>,
|
||||
pub(super) hover_point: Option<WebSurfaceClickPoint>,
|
||||
pub(super) click_point: Option<WebSurfaceClickState>,
|
||||
pub(super) pending_scroll_delta: Option<WebSurfaceScrollDelta>,
|
||||
pub(super) scroll_offset: Option<WebSurfaceScrollState>,
|
||||
pub(super) typed_text: Option<WebSurfaceTextInputState>,
|
||||
pub(super) state: Option<WebSurfaceState>,
|
||||
}
|
||||
|
||||
impl PerTabSurface {
|
||||
pub(super) fn new() -> Self {
|
||||
Self {
|
||||
viewport_bounds: None,
|
||||
viewport_size: None,
|
||||
pending_viewport_size: None,
|
||||
hover_point: None,
|
||||
click_point: None,
|
||||
pending_scroll_delta: None,
|
||||
scroll_offset: None,
|
||||
typed_text: None,
|
||||
state: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn scroll_offset_for(&self, requested_url: &str) -> WebSurfaceScrollOffset {
|
||||
self.scroll_offset
|
||||
.as_ref()
|
||||
.filter(|state| state.requested_url == requested_url)
|
||||
.map(|state| state.offset)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user