use std::cell::RefCell; use std::rc::Rc; use std::time::Instant; use gpui::{ AppContext as _, Context, Entity, IntoElement, ParentElement as _, Render, SharedString, Styled as _, TestAppContext, Window, div, }; use gpui_native_core::combobox::{Combobox, ComboboxOption, ComboboxState}; use gpui_native_core::init; fn option(label: &'static str) -> ComboboxOption { (SharedString::from(label), SharedString::from(label)) } struct Host { combobox: Entity>, renders: Rc>, } impl Render for Host { fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { *self.renders.borrow_mut() += 1; div().size_full().p_4().child(self.combobox.clone()) } } #[test] fn real_keystrokes_are_not_pathologically_slow() { let cx = TestAppContext::single(); cx.update(init); let (state, renders, window) = cx.update(|cx| { let renders = Rc::new(RefCell::new(0)); let state_cell: Rc>>>> = Rc::new(RefCell::new(None)); let renders_for_host = renders.clone(); let cell = state_cell.clone(); let window = cx .open_window(gpui::WindowOptions::default(), |window, cx| { let state = cx.new(|cx| { ComboboxState::new( Combobox::new( "bench-combo", "Fruit", vec![ option("main"), option("maintain"), option("release"), option("banana"), ], ), window, cx, ) }); let state_for_host = state.clone(); cell.borrow_mut().replace(state.clone()); cx.new(|_| Host { combobox: state_for_host, renders: renders_for_host, }) }) .unwrap(); let state = state_cell.borrow().clone().expect("state captured"); (state, renders, window) }); let mut visual = gpui::VisualTestContext::from_window(window.into(), &cx); visual.update(|window, cx| { state.update(cx, |state, cx| state.focus(window, cx)); window.draw(cx).clear(cx); }); let started = Instant::now(); for letter in "abcdefghijklmnopqrstuvwxyz".chars() { visual.simulate_keystrokes(&letter.to_string()); visual.update(|window, cx| { window.draw(cx).clear(cx); }); } let elapsed = started.elapsed(); let total_renders = *renders.borrow(); println!( "26 real keystrokes: {elapsed:?}, host renders: {total_renders} ({} per keystroke)", total_renders as f32 / 26. ); assert!(elapsed.as_millis() < 2000, "typing took {elapsed:?}"); }