mirror of
https://github.com/storytold/wordcraft.git
synced 2026-11-14 14:32:31 +00:00
ui: clear scroll replay tracking on root ui consumption (#6146)
This commit is contained in:
1 parent
1c3256ab65
commit
d6c68cbfbb
4 files changed
+52
-2
No files matched your search
@@ -422,6 +422,7 @@ impl WordApp {
|
||||
/// Lay out the windows: on the desktop each open document's in its own native window
|
||||
/// ([`windows`]), on the web the one window.
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
self.clear_raw_scroll_replay();
|
||||
if self.windows.native() {
|
||||
self.windows_ui(ui);
|
||||
} else {
|
||||
|
||||
@@ -8,8 +8,6 @@ impl WordApp {
|
||||
// a layout anyone will see. The shot's `issued` flag makes repeated final passes harmless.
|
||||
if !ctx.will_discard() {
|
||||
control::issue_screenshots(self, ctx);
|
||||
self.raw_scroll_events_scaled = 0;
|
||||
self.last_scaled_scroll_events.clear();
|
||||
}
|
||||
// The raw input was consumed by this host frame's passes; only a final UI pass proves
|
||||
// the step is done. A discarded pass keeps the queue for the next UI frame.
|
||||
|
||||
@@ -69,6 +69,12 @@ impl WordApp {
|
||||
self.last_scaled_scroll_events = raw.events.clone();
|
||||
}
|
||||
|
||||
/// Clears recorded scroll replay tracking when the UI pass consumes the frame's input.
|
||||
pub(crate) fn clear_raw_scroll_replay(&mut self) {
|
||||
self.raw_scroll_events_scaled = 0;
|
||||
self.last_scaled_scroll_events.clear();
|
||||
}
|
||||
|
||||
/// Whether this pass's input came from the control channel (`ui.click`, `ui.key`, `ui.drag`,
|
||||
/// `ui.text`…, which MCP's `click`, `key` and `type` tools send). Decisions that are only the
|
||||
/// user's ignore it: letting agent messages through again, and answering an agent's question
|
||||
|
||||
@@ -8277,3 +8277,48 @@ fn touchpad_point_scrolling_is_scaled_once_across_hidden_logic_ticks() {
|
||||
assert_eq!(delta.y, expected_fresh, "fresh input is scaled once");
|
||||
}
|
||||
}
|
||||
|
||||
/// Issue #6146 / PR #6167 review: replay tracking must be cleared when a warm-up UI pass
|
||||
/// consumes the input (which returns before `flush_shot_and_synthetic`), so a fresh event
|
||||
/// on the next frame whose delta happens to equal the previous scaled delta is not falsely
|
||||
/// treated as a replay.
|
||||
#[test]
|
||||
fn fresh_scroll_event_matching_previous_scaled_delta_is_scaled_after_warmup_ui() {
|
||||
let mut a = app();
|
||||
let ctx = egui::Context::default();
|
||||
let wheel_event = |y: f32| egui::Event::MouseWheel {
|
||||
unit: egui::MouseWheelUnit::Point,
|
||||
delta: egui::vec2(0.0, y),
|
||||
phase: egui::TouchPhase::Move,
|
||||
modifiers: egui::Modifiers::NONE,
|
||||
source: egui::MouseWheelSource::Unknown,
|
||||
};
|
||||
|
||||
// Ensure the app is in the warm-up phase (fonts_frames < 2).
|
||||
a.fonts_frames = 0;
|
||||
|
||||
// 1. First frame: incoming Point delta is -1.0. At Normal speed on Wayland, it scales to -4.0.
|
||||
let mut raw1 = egui::RawInput { events: vec![wheel_event(-1.0)], ..Default::default() };
|
||||
a.raw_input_hook(&ctx, &mut raw1);
|
||||
let factor = a.ui.touchpad_scroll_speed.touchpad_factor();
|
||||
let scaled_1 = -1.0 * factor;
|
||||
assert_eq!(raw1.events[0], wheel_event(scaled_1));
|
||||
|
||||
// 2. Warm-up UI pass runs: window_ui returns early because fonts_frames < 2.
|
||||
// This UI pass consumes raw1, so replay tracking must be cleared.
|
||||
ctx.run_ui(raw1, |ui| {
|
||||
a.ui(ui);
|
||||
})
|
||||
.drop_without_applying_deltas();
|
||||
assert_eq!(a.fonts_frames, 1, "first warm-up frame executed");
|
||||
|
||||
// 3. Second frame: fresh incoming event happens to have delta equal to scaled_1 (-4.0).
|
||||
// Because the previous frame's input was consumed by the UI, this is fresh input,
|
||||
// NOT a replay, so it must be scaled by factor (e.g. -4.0 * 4.0 = -16.0).
|
||||
let mut raw2 = egui::RawInput { events: vec![wheel_event(scaled_1)], ..Default::default() };
|
||||
a.raw_input_hook(&ctx, &mut raw2);
|
||||
let expected_2 = scaled_1 * factor;
|
||||
if let egui::Event::MouseWheel { delta, .. } = &raw2.events[0] {
|
||||
assert_eq!(delta.y, expected_2, "fresh event matching previous scaled delta must be scaled, not skipped as replay");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user