mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-14 11:17:10 -04:00
ui.move refuses a coordinate that isn't finite once narrowed to a
pointer position; ui.click {x, y} and ui.drag did not, so 1e39 became
an infinite position and was queued. With debug assertions on, the
next idle frame panicked in emath comparing NaN vectors.
Both now refuse such a coordinate with an error, as ui.move does, and
ui.drag also refuses ends too far apart for the way between them to
stay finite.
Adds click_and_drag_refuse_coordinates_that_overflow_like_move in
tests/control.rs, which panics before this change.
This commit is contained in:
1 parent
cced834190
commit
595026aa69
2 files changed
+36
-2
No files matched your search
@@ -397,11 +397,16 @@ impl Control {
|
||||
fn drag(&mut self, p: &Value) -> Result<Handled, String> {
|
||||
let point = |k: &str| -> Result<egui::Pos2, String> {
|
||||
match p.get(k).and_then(Value::as_array).map(|a| a.iter().filter_map(Value::as_f64).collect::<Vec<_>>()).as_deref() {
|
||||
Some([x, y]) => Ok(egui::pos2(*x as f32, *y as f32)),
|
||||
Some([x, y]) => Some(egui::pos2(*x as f32, *y as f32))
|
||||
.filter(|pos| pos.is_finite())
|
||||
.ok_or_else(|| format!("ui.drag: {k} must be [x, y], finite coordinates in points")),
|
||||
_ => Err(format!("ui.drag: {k} must be [x, y] in points")),
|
||||
}
|
||||
};
|
||||
let (from, to) = (point("from")?, point("to")?);
|
||||
if !(to - from).is_finite() {
|
||||
return Err("ui.drag: from and to must be a finite distance apart, in points".into());
|
||||
}
|
||||
let steps = p.get("steps").and_then(Value::as_u64).unwrap_or(8).clamp(1, 200) as usize;
|
||||
let modifiers = modifiers(p.get("modifiers"))?;
|
||||
let which = pointer_button(p, "ui.drag")?;
|
||||
@@ -417,7 +422,10 @@ impl Control {
|
||||
|
||||
fn click(&mut self, p: &Value) -> Result<Handled, String> {
|
||||
if let (Some(x), Some(y)) = (p.get("x").and_then(Value::as_f64), p.get("y").and_then(Value::as_f64)) {
|
||||
let pos = egui::pos2(x as f32, y as f32);
|
||||
let point = |key: &str, n: f64| {
|
||||
Some(n as f32).filter(|n| n.is_finite()).ok_or_else(|| format!("ui.click: {key} must be a finite coordinate in points"))
|
||||
};
|
||||
let pos = egui::pos2(point("x", x)?, point("y", y)?);
|
||||
let which = pointer_button(p, "ui.click")?;
|
||||
let button = |pressed| egui::Event::PointerButton { pos, button: which, pressed, modifiers: egui::Modifiers::NONE };
|
||||
let frames = self.inject(vec![vec![egui::Event::PointerMoved(pos)], vec![button(true)], vec![button(false)]]);
|
||||
|
||||
@@ -1550,3 +1550,29 @@ fn initial_zoom_option_is_applied_before_the_first_viewport_layout() {
|
||||
assert_eq!(h.state().views[0].zoom, percent as f32 / 100.0);
|
||||
}
|
||||
}
|
||||
|
||||
/// #1306: a coordinate that only overflows once narrowed to a pointer position is refused by
|
||||
/// click and drag, as move refuses it, before any pointer input is queued; the frames that follow
|
||||
/// run, and the channel keeps working.
|
||||
#[test]
|
||||
fn click_and_drag_refuse_coordinates_that_overflow_like_move() {
|
||||
let (mut h, c) = harness();
|
||||
for (method, params) in [
|
||||
("ui.move", json!({ "x": 1e39, "y": -1e39 })),
|
||||
("ui.click", json!({ "x": 1e39, "y": -1e39 })),
|
||||
("ui.click", json!({ "x": 40.0, "y": 1e39 })),
|
||||
("ui.drag", json!({ "from": [1e39, -1e39], "to": [40.0, 40.0], "steps": 1 })),
|
||||
("ui.drag", json!({ "from": [40.0, 40.0], "to": [40.0, -1e39], "steps": 1 })),
|
||||
// Each end fits, but not the way from one to the other.
|
||||
("ui.drag", json!({ "from": [-3e38, 40.0], "to": [3e38, 40.0], "steps": 1 })),
|
||||
] {
|
||||
let e = call(&mut h, &c, method, params.clone()).expect_err(&format!("{method} {params} is refused"));
|
||||
assert!(e.starts_with(&format!("{method}: ")) && e.contains("finite"), "{e}");
|
||||
h.run_steps(4);
|
||||
assert_eq!(ok(&mut h, &c, "ui.inspect", json!({ "query": "Read", "role": "Button" }))["count"], 1);
|
||||
}
|
||||
let read = ok(&mut h, &c, "ui.inspect", json!({ "query": "Read", "role": "Button" }))["widgets"][0]["rect"].clone();
|
||||
let (x, y) = (read[0].as_f64().unwrap() + 4.0, read[1].as_f64().unwrap() + 4.0);
|
||||
assert_eq!(ok(&mut h, &c, "ui.click", json!({ "x": x, "y": y }))["clicked"], json!([x, y]));
|
||||
ok(&mut h, &c, "ui.drag", json!({ "from": [x, y], "to": [x + 10.0, y], "steps": 2 }));
|
||||
}
|
||||
Reference in new issue
Block a user