forked from reya/gpui-native-kit
chore: reduce component overhead (#3)
Reviewed-on: reya/gpui-native-kit#3
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use std::{cell::Cell, rc::Rc, time::Duration};
|
||||
|
||||
use gpui::{
|
||||
AppContext as _, Context, Entity, IntoElement, ParentElement as _, Render, SharedString,
|
||||
Styled as _, TestAppContext, VisualTestContext, Window, div,
|
||||
@@ -9,10 +11,12 @@ use gpui_native_core::input::{Input, InputState};
|
||||
|
||||
struct FieldHost {
|
||||
url: Entity<InputState>,
|
||||
renders: Rc<Cell<usize>>,
|
||||
}
|
||||
|
||||
impl Render for FieldHost {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
self.renders.set(self.renders.get() + 1);
|
||||
let url_error = self
|
||||
.url
|
||||
.read(cx)
|
||||
@@ -34,15 +38,27 @@ impl Render for FieldHost {
|
||||
|
||||
/// A field page in a real window; the url input is focused unless
|
||||
/// `focus` is false, which leaves the page truly idle.
|
||||
fn field_host(focus: bool) -> (TestAppContext, Entity<InputState>, VisualTestContext) {
|
||||
fn field_host(
|
||||
focus: bool,
|
||||
) -> (
|
||||
TestAppContext,
|
||||
Entity<InputState>,
|
||||
VisualTestContext,
|
||||
Rc<Cell<usize>>,
|
||||
) {
|
||||
let cx = TestAppContext::single();
|
||||
cx.update(init);
|
||||
let renders = Rc::new(Cell::new(0));
|
||||
let renders_for_host = renders.clone();
|
||||
let (url, window) = cx.update(|cx| {
|
||||
let url = InputState::new(cx);
|
||||
let url_for_host = url.clone();
|
||||
let window = cx
|
||||
.open_window(gpui::WindowOptions::default(), |_, cx| {
|
||||
cx.new(|_| FieldHost { url: url_for_host })
|
||||
cx.new(|_| FieldHost {
|
||||
url: url_for_host,
|
||||
renders: renders_for_host.clone(),
|
||||
})
|
||||
})
|
||||
.unwrap();
|
||||
(url, window)
|
||||
@@ -55,12 +71,12 @@ fn field_host(focus: bool) -> (TestAppContext, Entity<InputState>, VisualTestCon
|
||||
}
|
||||
window.draw(cx).clear(cx);
|
||||
});
|
||||
(cx, url, visual)
|
||||
(cx, url, visual, renders)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_idle_field_page_schedules_no_frames() {
|
||||
let (_cx, _url, mut visual) = field_host(false);
|
||||
let (_cx, _url, mut visual, _renders) = field_host(false);
|
||||
let frames = visual.update(|window, cx| window.simulate_next_frame(cx));
|
||||
assert_eq!(
|
||||
frames, 0,
|
||||
@@ -68,12 +84,25 @@ fn an_idle_field_page_schedules_no_frames() {
|
||||
);
|
||||
}
|
||||
|
||||
/// The caret blink is fps-capped: it must never demand a next frame, and its
|
||||
/// redraws arrive on the executor timer at the blink cadence.
|
||||
#[test]
|
||||
fn a_focused_field_page_schedules_frames_for_its_blink() {
|
||||
let (_cx, _url, mut visual) = field_host(true);
|
||||
fn a_focused_field_blink_is_fps_capped_and_still_redraws() {
|
||||
let (cx, _url, mut visual, renders) = field_host(true);
|
||||
let renders_after_focus = renders.get();
|
||||
|
||||
let frames = visual.update(|window, cx| window.simulate_next_frame(cx));
|
||||
assert_eq!(
|
||||
frames, 0,
|
||||
"the blink must be fps-capped, not per-frame scheduled"
|
||||
);
|
||||
|
||||
// The blink redraws through the executor timer (4 fps cap).
|
||||
cx.executor().advance_clock(Duration::from_millis(251));
|
||||
cx.run_until_parked();
|
||||
visual.update(|window, cx| window.draw(cx).clear(cx));
|
||||
assert!(
|
||||
frames > 0,
|
||||
"the focused caret's blink needs frames to redraw at the blink cadence"
|
||||
renders.get() > renders_after_focus,
|
||||
"the capped blink must still redraw its page"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user