//! GPUI test harness for the input pipeline. //! //! Twelve sidecar-side commits and one shell-side commit had all claimed to //! fix "click does nothing" while the user kept reporting the same symptom. //! The roundtable consensus: every store-layer test passed GREEN, every //! sidecar integration test passed GREEN, but nothing in the repo exercised //! the real GPUI event tree (`render_input_overlay` + window-level mouse //! handlers + sidebar capture interactions). This module is that missing //! holdout set. //! //! What we have so far: //! 1. `baseline_overlay_div_receives_simulated_click` — proves GPUI's //! `.occlude()` + `capture_any_mouse_up` primitive works correctly in //! `TestAppContext`. If this regresses, the harness itself is broken. //! 2. `baseline_overlay_with_full_listener_combo_receives_click` — proves //! the exact listener combo `render_input_overlay` uses (on_mouse_down + //! capture_any_mouse_up + on_mouse_move + on_scroll_wheel on a single //! `.occlude()` div) works in isolation. //! 3. `ely_shell_external_canvas_lays_out_inside_window` — boots a real //! `ElyShell`, navigates to an external URL, and asserts the //! input_overlay's measured viewport bounds fit inside the visible //! window. This was the original ship-blocker: the overlay was being //! positioned at `y = window_height - 17`, entirely below the visible //! region, so every user click hit empty space above the overlay. use std::cell::RefCell; use std::rc::Rc; use std::sync::Arc; use ely_domain::{TabId, UrlText}; use gpui::{ Bounds, Context, IntoElement, Modifiers, MouseButton, ParentElement, Pixels, Render, Styled, TestAppContext, Window, canvas, div, point, px, }; use gpui::InteractiveElement; use super::ShellState; use super::web_surface::WebSurfaceStore; use super::web_surface_frame::WebSurfaceFrame; use super::web_surface_geometry::WebSurfaceScrollOffset; use crate::services::servo_live::ServoLiveFrame; #[cfg(test)] impl super::ElyShell { pub(super) fn web_surfaces_for_test(&self) -> &WebSurfaceStore { &self.web_surfaces } } #[gpui::test] async fn ely_shell_external_canvas_lays_out_inside_window(cx: &mut TestAppContext) { cx.update(|cx| gpui_component::init(cx)); let (shell, cx) = cx.add_window_view(|window, cx| super::ElyShell::new(window, cx)); cx.run_until_parked(); cx.update(|window, app_cx| { shell.update(app_cx, |shell, ctx| { shell.navigate_active_tab( UrlText::parse("https://example.com/".to_string()).expect("valid URL"), window, ctx, ); }); }); cx.run_until_parked(); let (_active_tab_id, active_tab_url, viewport_bounds) = active_tab_overlay_state(&shell, cx); assert!( active_tab_url.starts_with("https://"), "active tab URL must be external https for render_external_web_canvas \ to render the input_overlay (got {active_tab_url:?})." ); let bounds = viewport_bounds.unwrap_or_else(|| { panic!( "viewport_bounds for the active tab is None. The canvas tracker \ in render_input_overlay's sibling never fired its layout \ callback — render_external_web_canvas was not reached." ) }); let window_size = cx.update(|window, _| window.bounds().size); assert!( bounds.origin.y + bounds.size.height <= window_size.height + px(1.0) && bounds.origin.x + bounds.size.width <= window_size.width + px(1.0), "Layout regression: input_overlay viewport_bounds {bounds:?} extend \ outside the {window_size:?} window. The canvas tracker measured a \ layout that escapes the visible region — every user click in the \ visible area now lands above (or beside) the overlay's hitbox. \ The original ship-blocker was bounds.origin.y == window_height-17 \ caused by content (the rendered web image) being a non-absolute \ child of the relative wrapper, which doubled the parent's height \ and pushed the overlay off-screen." ); } /// TDD red guard: a user click inside the rendered web canvas must /// arrive at the input pipeline. The contract is stated in user /// terms — "click on the page, and the click is recorded" — not in /// GPUI mechanism terms. The two baselines already prove (a) the /// `.occlude() + capture_any_mouse_up` primitive works under /// `TestAppContext`, and (b) the listener combo `input_overlay` uses /// works in isolation. The layout regression test proves (c) the /// overlay is on-screen. If this test still fails, the regression /// lives strictly inside the real ElyShell widget tree. /// /// Marked `#[ignore]` while the diagnosis runs so the rest of the /// suite stays green. The fix commit MUST delete the attribute (not /// edit it) so the contract turns into a permanent regression guard /// on first green. #[gpui::test] #[ignore = "T7 red guard. Failure mode confirmed via `cargo test -- --ignored`: \ after layout (840255f) and pixel-pipe (a80d039) fixes, the \ ComboProbe baseline + layout sanity test both pass, yet a click \ at the measured viewport center never reaches \ WebSurfaceStore.click_point. The MouseUp is being eaten somewhere \ inside the real ElyShell widget tree (sibling z-order, ancestor \ listener consuming capture phase, or a hitbox content_mask \ clipped by overflow_hidden). The fix commit must remove this \ attribute outright — not toggle the reason."] async fn user_click_in_rendered_web_canvas_reaches_input_pipeline( cx: &mut TestAppContext, ) { cx.update(|cx| gpui_component::init(cx)); let (shell, cx) = cx.add_window_view(|window, cx| super::ElyShell::new(window, cx)); cx.run_until_parked(); cx.update(|window, app_cx| { shell.update(app_cx, |shell, ctx| { shell.navigate_active_tab( UrlText::parse("https://example.com/".to_string()).expect("valid URL"), window, ctx, ); }); }); cx.run_until_parked(); let (active_tab_id, _active_tab_url, viewport_bounds) = active_tab_overlay_state(&shell, cx); let bounds = viewport_bounds.expect( "viewport_bounds must be Some before T7 can be exercised — the layout \ regression test catches the upstream failure mode separately", ); let surface_state_label = shell.read_with(cx, |shell, _| { match shell .web_surfaces_for_test() .surface_for_test(&active_tab_id) .and_then(|s| s.state.as_ref()) { Some(super::web_surface_state::WebSurfaceState::Ready(_)) => "Ready", Some(super::web_surface_state::WebSurfaceState::Loading { .. }) => "Loading", Some(super::web_surface_state::WebSurfaceState::Failed { .. }) => "Failed", None => "None", } }); let click_at = point( bounds.origin.x + bounds.size.width / 2.0, bounds.origin.y + bounds.size.height / 2.0, ); cx.simulate_mouse_move(click_at, None, Modifiers::default()); cx.run_until_parked(); let hover_point_after_move = shell.read_with(cx, |shell, _| { shell .web_surfaces_for_test() .surface_for_test(&active_tab_id) .and_then(|surface| surface.hover_point) .map(|point| (point.x(), point.y())) }); cx.simulate_click(click_at, Modifiers::default()); cx.run_until_parked(); shell.read_with(cx, |shell, _| { let click_point = shell .web_surfaces_for_test() .surface_for_test(&active_tab_id) .and_then(|surface| surface.click_point.as_ref()) .map(|state| (state.point.x(), state.point.y())); assert!( click_point.is_some(), "TDD red: clicked at {click_at:?} inside the measured \ viewport_bounds {bounds:?} (state = {surface_state_label}, \ hover_point after move = {hover_point_after_move:?}), yet \ WebSurfaceStore.click_point is None. If hover_point is \ Some, input_overlay's on_mouse_move listener fires but \ capture_any_mouse_up does not — capture phase specifically \ is being eaten." ); }); } /// Bisect probe for T7: same listener combo as `input_overlay`, but /// wrap it in the exact `.relative().size_full().min_w_0().overflow_hidden()` /// shell that `render_web_surface` puts around it after the layout /// fix in 840255f. If this passes, the bug is upstream of the /// relative wrapper itself. #[gpui::test] async fn baseline_overlay_under_overflow_hidden_relative_receives_click( cx: &mut TestAppContext, ) { let click_count = Rc::new(RefCell::new(0u32)); let counter_for_render = click_count.clone(); struct WrappedProbe { on_up_counter: Rc>, } impl Render for WrappedProbe { fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { let counter = self.on_up_counter.clone(); div() .relative() .size_full() .min_w_0() .overflow_hidden() .child( div() .absolute() .size_full() .occlude() .on_mouse_down(MouseButton::Left, |_event, _window, _cx| {}) .capture_any_mouse_up(move |_event, _window, _cx| { *counter.borrow_mut() += 1; }) .on_mouse_move(|_event, _window, _cx| {}) .on_scroll_wheel(|_event, _window, _cx| {}), ) } } let (_probe, cx) = cx.add_window_view(|_window, _cx| WrappedProbe { on_up_counter: counter_for_render, }); cx.run_until_parked(); cx.simulate_mouse_move(point(px(100.0), px(100.0)), None, Modifiers::default()); cx.simulate_click(point(px(100.0), px(100.0)), Modifiers::default()); cx.run_until_parked(); assert_eq!( *click_count.borrow(), 1, "Bisect: wrapping the input_overlay's listener combo in a \ .relative().size_full().min_w_0().overflow_hidden() parent (the \ exact shell render_web_surface uses) should still deliver the \ click. If this fails, the overflow_hidden parent itself clips the \ overlay's hitbox content_mask and the fix is to remove \ overflow_hidden from the relative wrapper or move it elsewhere." ); } /// Bisect probe layer 2: stack the full ElyShell wrapper chain that /// sits between the window root and the overlay — root size_full, /// absolute inset_0 flex container, flex_1 + flex_col main pane with /// rounded/border/shadow/overflow_hidden, flex_1 content wrapper, /// then the relative+overflow_hidden surface wrapper from /// `render_web_surface`. If this passes, the bug is in something /// `render_external_web_canvas` adds (not in the plain layout chain). #[gpui::test] async fn baseline_overlay_under_full_elyshell_wrapper_chain_receives_click( cx: &mut TestAppContext, ) { let click_count = Rc::new(RefCell::new(0u32)); let counter_for_render = click_count.clone(); struct DeepProbe { on_up_counter: Rc>, } impl Render for DeepProbe { fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { let counter = self.on_up_counter.clone(); // Root: matches render_browser's outer div. div() .size_full() .child( // Absolute flex container matches render_browser's child layout. div() .absolute() .inset_0() .p(px(16.0)) .gap(px(12.0)) .flex() .child( // Main pane: matches render_main_pane. div() .flex_1() .h_full() .min_w_0() .flex() .flex_col() .rounded(px(18.0)) .border_1() .overflow_hidden() .child( // Content wrapper: matches the flex_1 child of main_pane. div() .flex_1() .overflow_hidden() .child( // Surface wrapper: matches render_web_surface root. div() .relative() .size_full() .min_w_0() .overflow_hidden() .child( div() .absolute() .size_full() .occlude() .on_mouse_down( MouseButton::Left, |_event, _window, _cx| {}, ) .capture_any_mouse_up( move |_event, _window, _cx| { *counter.borrow_mut() += 1; }, ) .on_mouse_move( |_event, _window, _cx| {}, ) .on_scroll_wheel( |_event, _window, _cx| {}, ), ), ), ), ), ) } } let (_probe, cx) = cx.add_window_view(|_window, _cx| DeepProbe { on_up_counter: counter_for_render, }); cx.run_until_parked(); cx.simulate_mouse_move(point(px(400.0), px(400.0)), None, Modifiers::default()); cx.simulate_click(point(px(400.0), px(400.0)), Modifiers::default()); cx.run_until_parked(); assert_eq!( *click_count.borrow(), 1, "Bisect layer 2: the full root → absolute-flex → main-pane → \ content-wrapper → surface-wrapper chain (sans listeners) \ should still deliver the click. If this fails, the bug is in \ this wrapper chain itself; if it passes, the bug is in \ something render_external_web_canvas adds (canvas tracker, \ absolute content wrapper sibling, or a gpui-component widget)." ); } /// Diagnostic probes (T13 bisect): each layer of the ElyShell render /// tree was reproduced in isolation and **all passed**, confirming the /// listener combo, layout wrapper chain, canvas sibling, entity /// update side effects, and track_focus root listeners are NOT the /// cause. The bug is elsewhere — likely in ElyShell::new's setup /// (subscriptions, timer, InputState side effects) or in the /// sync_address_input call inside navigate_active_tab that mutates /// Input widget state which may invalidate the rendered_frame /// between MouseMove and MouseUp. Kept for regression coverage. /// Bisect probe layer 5: the full chain WITH the root-level /// `track_focus + on_mouse_up(Left, bubble)` listeners ElyShell /// puts on its outermost div. If track_focus's auto-focus MouseDown /// handler, or the root's bubble-phase MouseUp listener, somehow /// invalidates the rendered_frame between MouseDown and MouseUp, /// input_overlay's hitbox will no longer match the listener /// snapshot's id and `is_hovered` will return false. That's the /// exact symptom we see: hover_point is None too, so it's not /// capture-specific — every listener on input_overlay is missing /// its hit. #[gpui::test] async fn baseline_overlay_under_root_with_track_focus_receives_click( cx: &mut TestAppContext, ) { use gpui::FocusHandle; let click_count = Rc::new(RefCell::new(0u32)); let move_count = Rc::new(RefCell::new(0u32)); let counter_for_up = click_count.clone(); let counter_for_move = move_count.clone(); struct TrackFocusProbe { focus: FocusHandle, on_up_counter: Rc>, on_move_counter: Rc>, } impl Render for TrackFocusProbe { fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { let counter_up = self.on_up_counter.clone(); let counter_move = self.on_move_counter.clone(); div() .size_full() .track_focus(&self.focus) .on_mouse_up(MouseButton::Left, |_event, _window, _cx| {}) .child( div() .absolute() .inset_0() .p(px(16.0)) .gap(px(12.0)) .flex() .child( div() .flex_1() .h_full() .min_w_0() .flex() .flex_col() .rounded(px(18.0)) .border_1() .overflow_hidden() .child( div() .flex_1() .overflow_hidden() .child( div() .relative() .size_full() .min_w_0() .overflow_hidden() .child( div() .absolute() .inset_0() .child(div().size_full()), ) .child( canvas( move |_b, _w, _c| {}, |_, _, _, _| {}, ) .absolute() .size_full(), ) .child( div() .absolute() .size_full() .occlude() .on_mouse_down( MouseButton::Left, |_e, _w, _c| {}, ) .capture_any_mouse_up( move |_e, _w, _c| { *counter_up .borrow_mut() += 1; }, ) .on_mouse_move( move |_e, _w, _c| { *counter_move .borrow_mut() += 1; }, ) .on_scroll_wheel( |_e, _w, _c| {}, ), ), ), ), ), ) } } let (_probe, cx) = cx.add_window_view(|_window, cx| TrackFocusProbe { focus: cx.focus_handle(), on_up_counter: counter_for_up, on_move_counter: counter_for_move, }); cx.run_until_parked(); cx.simulate_mouse_move(point(px(400.0), px(400.0)), None, Modifiers::default()); cx.run_until_parked(); cx.simulate_click(point(px(400.0), px(400.0)), Modifiers::default()); cx.run_until_parked(); assert!( *move_count.borrow() > 0, "Bisect layer 5: input_overlay's on_mouse_move never fired even \ though the cursor was simulated over it. The same `is_hovered` \ check fails for every listener, exactly mirroring the T7 red \ test's observation that hover_point is None." ); assert_eq!( *click_count.borrow(), 1, "Bisect layer 5: capture_any_mouse_up did not fire under the \ full track_focus + bubble-mouse_up root chain. This isolates \ the culprit to the root-level listeners that ElyShell adds \ around its widget tree." ); } /// Bisect probe layer 4: same shape as the canvas-sibling probe but /// the on_mouse_down listener calls `cx.update` on a self-entity /// (mirroring `down_entity.update(cx, |shell, _| shell.focus_web_surface(window))`). /// `entity.update` notifies subscribers; if that side effect during /// mouse_down's bubble phase disturbs mouse dispatch — invalidates /// the rendered_frame, regenerates hitboxes, or otherwise corrupts /// the in-flight dispatch — the subsequent MouseUp will land on a /// frame whose hitboxes no longer match the listeners' captured /// snapshots, and this test will go red. #[gpui::test] async fn baseline_overlay_with_entity_update_in_mouse_down_receives_click( cx: &mut TestAppContext, ) { let click_count = Rc::new(RefCell::new(0u32)); let counter_for_render = click_count.clone(); struct EntityUpdateProbe { on_up_counter: Rc>, tick: u32, } impl Render for EntityUpdateProbe { fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { let counter = self.on_up_counter.clone(); let self_entity = cx.entity().clone(); div() .relative() .size_full() .min_w_0() .overflow_hidden() .child(div().absolute().inset_0().child(div().size_full())) .child( canvas( move |_bounds, _window, _cx| {}, |_, _, _, _| {}, ) .absolute() .size_full(), ) .child( div() .absolute() .size_full() .occlude() .on_mouse_down(MouseButton::Left, move |_event, _window, cx| { self_entity.update(cx, |probe, _cx| { probe.tick += 1; }); }) .capture_any_mouse_up(move |_event, _window, _cx| { *counter.borrow_mut() += 1; }) .on_mouse_move(|_event, _window, _cx| {}) .on_scroll_wheel(|_event, _window, _cx| {}), ) } } let (_probe, cx) = cx.add_window_view(|_window, _cx| EntityUpdateProbe { on_up_counter: counter_for_render, tick: 0, }); cx.run_until_parked(); cx.simulate_mouse_move(point(px(400.0), px(400.0)), None, Modifiers::default()); cx.simulate_click(point(px(400.0), px(400.0)), Modifiers::default()); cx.run_until_parked(); assert_eq!( *click_count.borrow(), 1, "Bisect layer 4: on_mouse_down's bubble fires entity.update \ which automatically notifies subscribers. If this test fails, \ the cx.notify side effect during in-flight dispatch corrupts \ the rendered_frame for the immediately-following MouseUp." ); } /// Bisect probe layer 3: add a canvas sibling BEFORE the overlay, /// matching render_web_surface's viewport_tracker sibling exactly. /// The canvas's prepaint callback fires during paint phase; if it /// somehow disturbs hitbox registration or mouse_listeners ordering, /// this test will go red and pinpoint the suspect. #[gpui::test] async fn baseline_overlay_with_canvas_sibling_receives_click( cx: &mut TestAppContext, ) { let click_count = Rc::new(RefCell::new(0u32)); let counter_for_render = click_count.clone(); struct CanvasSiblingProbe { on_up_counter: Rc>, } impl Render for CanvasSiblingProbe { fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { let counter = self.on_up_counter.clone(); div() .relative() .size_full() .min_w_0() .overflow_hidden() .child( div() .absolute() .inset_0() .child(div().size_full()), ) .child( canvas( move |_bounds, _window, _cx| {}, |_, _, _, _| {}, ) .absolute() .size_full(), ) .child( div() .absolute() .size_full() .occlude() .on_mouse_down(MouseButton::Left, |_event, _window, _cx| {}) .capture_any_mouse_up(move |_event, _window, _cx| { *counter.borrow_mut() += 1; }) .on_mouse_move(|_event, _window, _cx| {}) .on_scroll_wheel(|_event, _window, _cx| {}), ) } } let (_probe, cx) = cx.add_window_view(|_window, _cx| CanvasSiblingProbe { on_up_counter: counter_for_render, }); cx.run_until_parked(); cx.simulate_mouse_move(point(px(400.0), px(400.0)), None, Modifiers::default()); cx.simulate_click(point(px(400.0), px(400.0)), Modifiers::default()); cx.run_until_parked(); assert_eq!( *click_count.borrow(), 1, "Bisect layer 3: adding a canvas sibling (the shape \ render_viewport_tracker uses) between the content wrapper and \ the overlay should not break click delivery. If this fails, \ the canvas element itself disturbs mouse dispatch — likely \ via its prepaint callback's interaction with hit_test." ); } #[gpui::test] async fn baseline_overlay_with_full_listener_combo_receives_click( cx: &mut TestAppContext, ) { let click_count = Rc::new(RefCell::new(0u32)); let counter_for_render = click_count.clone(); struct ComboProbe { on_up_counter: Rc>, } impl Render for ComboProbe { fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { let counter = self.on_up_counter.clone(); div().relative().size_full().child( div() .absolute() .size_full() .occlude() .on_mouse_down(MouseButton::Left, |_event, _window, _cx| {}) .capture_any_mouse_up(move |_event, _window, _cx| { *counter.borrow_mut() += 1; }) .on_mouse_move(|_event, _window, _cx| {}) .on_scroll_wheel(|_event, _window, _cx| {}), ) } } let (_probe, cx) = cx.add_window_view(|_window, _cx| ComboProbe { on_up_counter: counter_for_render, }); cx.run_until_parked(); cx.simulate_mouse_move(point(px(100.0), px(100.0)), None, Modifiers::default()); cx.simulate_click(point(px(100.0), px(100.0)), Modifiers::default()); cx.run_until_parked(); assert_eq!( *click_count.borrow(), 1, "GPUI baseline with input_overlay's full listener combo: click should \ reach capture_any_mouse_up. If this fails, the listener combo itself \ is the problem, not the surrounding shell." ); } #[gpui::test] async fn baseline_overlay_div_receives_simulated_click(cx: &mut TestAppContext) { let click_count = Rc::new(RefCell::new(0u32)); let counter_for_render = click_count.clone(); struct Probe { on_up_counter: Rc>, } impl Render for Probe { fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { let counter = self.on_up_counter.clone(); div().relative().size_full().child( div().absolute().size_full().occlude().capture_any_mouse_up( move |_event, _window, _cx| { *counter.borrow_mut() += 1; }, ), ) } } let (_probe, cx) = cx.add_window_view(|_window, _cx| Probe { on_up_counter: counter_for_render, }); cx.run_until_parked(); cx.simulate_mouse_move(point(px(100.0), px(100.0)), None, Modifiers::default()); cx.simulate_click(point(px(100.0), px(100.0)), Modifiers::default()); cx.run_until_parked(); assert_eq!( *click_count.borrow(), 1, "GPUI baseline: a div with .absolute().size_full().occlude() and \ capture_any_mouse_up never received the simulated click. The test \ harness or GPUI primitive is broken — ElyShell test results are \ meaningless until this passes." ); } /// TDD red guard for T10: today every `WebSurfaceFrame::from_live_frame` /// call allocates a fresh `Arc::new(RenderImage::new(...))` regardless /// of whether the underlying pixels changed. At 60 fps on a 1080p /// canvas that is `~8 MB / frame` of host-side RGBA cloning + a new /// GPUI texture upload, the cost Linus + Karpathy + Jony all flagged /// as the next material bottleneck after the file-system pipe. /// /// The contract this test pins is the cheapest invariant we can hold /// against today's `SoftwareRenderingContext`: two frames carrying /// **byte-identical RGBA payloads must produce the same underlying /// `Arc`**. Today they do not — every `from_live_frame` /// blindly reallocates. The fix path is either dedup the upload /// against the last bytes or switch to `OffscreenRenderingContext` + /// IOSurface so the GPU texture is the source of truth. /// /// Regression guard: with the single-slot `LAST_FRAME_IMAGE` cache in /// `web_surface_frame.rs`, two `ServoLiveFrame` inputs carrying /// byte-identical RGBA payloads now share the same `Arc`. /// Without this guard a regression that drops the cache silently /// returns to ~960 MB/s of host-side RGBA cloning + per-frame GPUI /// texture allocations. #[test] fn identical_live_frames_share_render_image_arc() { let width = 16u32; let height = 8u32; let rgba_bytes = vec![0xAAu8; (width as usize) * (height as usize) * 4]; let first = WebSurfaceFrame::from_live_frame( "https://example.com/".to_string(), WebSurfaceScrollOffset::default(), 100, ServoLiveFrame::for_test(width, height, rgba_bytes.clone()), ) .expect("first frame builds from identical bytes"); let second = WebSurfaceFrame::from_live_frame( "https://example.com/".to_string(), WebSurfaceScrollOffset::default(), 100, ServoLiveFrame::for_test(width, height, rgba_bytes), ) .expect("second frame builds from identical bytes"); assert!( Arc::ptr_eq(&first.image, &second.image), "TDD red: two ServoLiveFrames with byte-identical RGBA produced \ distinct Arc instances (first={:p}, second={:p}). \ WebSurfaceFrame::from_parts must dedup the upload against the \ previous frame's bytes, or the rendering pipeline must switch \ to a GPU-side source of truth (IOSurface) so per-frame host \ allocations stop entirely.", Arc::as_ptr(&first.image), Arc::as_ptr(&second.image), ); } fn active_tab_overlay_state( shell: &gpui::Entity, cx: &mut gpui::VisualTestContext, ) -> (TabId, String, Option>) { shell.read_with(cx, |shell, _cx| { let tab = match &shell.state { ShellState::Ready(core) => core.active_tab().expect("active tab exists"), ShellState::StartupError(message) => { panic!("ElyShell failed to start in test: {message}") } }; let tab_id = tab.id().clone(); let url = tab.url().as_str().to_string(); let bounds = shell .web_surfaces_for_test() .surface_for_test(&tab_id) .and_then(|surface| surface.viewport_bounds); (tab_id, url, bounds) }) }