mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-07 20:23:35 +00:00
MCP: given-up stale pointer requests do not use up a frame's request limit
A ui.pointer request made before synthetic input was dropped counted toward the per-frame request limit even when its caller had already given it up and no reply was sent. A backlog of such requests could hold live requests back for a frame. It now counts only when the app claims it and replies with the error, as the other given-up requests are skipped.
This commit is contained in:
@@ -13,8 +13,9 @@ impl VectorcraftApp {
|
||||
// Synthetic input sent before this pointer request was dropped (see
|
||||
// `discard_stale_injected_batch`): its events would reach the tool without that input.
|
||||
if req.method == "ui.pointer" && req.made_before(self.synthetic_dropped_before) {
|
||||
handled += 1;
|
||||
// One its caller gave up is skipped without counting toward this frame's limit.
|
||||
if req.claim() {
|
||||
handled += 1;
|
||||
let _ = req.reply.send(json!({
|
||||
"ok": false,
|
||||
"error": "input sent before this pointer request was dropped because the document, dialog or focus changed"
|
||||
|
||||
@@ -142,6 +142,27 @@ fn a_given_up_pointer_does_not_hold_back_later_requests() {
|
||||
assert!(up_reply.try_recv().is_err(), "the given-up pointer request did not run");
|
||||
}
|
||||
|
||||
/// Given-up `ui.pointer` requests made before synthetic input was dropped do not count toward a
|
||||
/// frame's request limit: a request queued behind a frame's worth of them runs in that frame.
|
||||
#[test]
|
||||
fn given_up_stale_pointer_requests_do_not_use_up_the_frame() {
|
||||
let (tx, rx) = std::sync::mpsc::channel();
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default()).with_control(rx);
|
||||
app.run("file.new", json!({"width": 300, "height": 300})).unwrap();
|
||||
let ctx = egui::Context::default();
|
||||
for _ in 0..crate::control::MAX_CONTROL_REQUESTS_PER_FRAME {
|
||||
let (up, _up_reply) = ControlRequest::new("ui.pointer", json!({"events": [{"kind": "up", "x": 200, "y": 180}]}));
|
||||
assert!(up.ticket().give_up(), "the pointer request had not started");
|
||||
tx.send(up).unwrap();
|
||||
}
|
||||
app.synthetic_dropped_before = ControlRequest::next_seq();
|
||||
let (list, list_reply) = ControlRequest::new("ui.tool.list", json!({}));
|
||||
tx.send(list).unwrap();
|
||||
app.drain_control(&ctx);
|
||||
let r = list_reply.try_recv().expect("the list ran in the same frame");
|
||||
assert_eq!(r["ok"], true, "{r}");
|
||||
}
|
||||
|
||||
/// A `ui.pointer` release sent after a `ui.key` fails when the key's batch is discarded because a
|
||||
/// dialog opened before a UI pass took it, whether the release was waiting for the key
|
||||
/// (`waiting`) or still on the channel. A release made after the discard runs.
|
||||
|
||||
Reference in New Issue
Block a user