Dispatch source hit testing for native pointer clicks
Verify Tessera GUI / verify (push) Failing after 7m31s
Verify Tessera GUI / verify (push) Failing after 7m31s
This commit is contained in:
+82
-5
@@ -94,6 +94,13 @@ impl NativeCallable for Method {
|
||||
}
|
||||
let geometry = mount.geometry.clone();
|
||||
let input = object(input)?;
|
||||
if matches!(self.query, Query::HitTest) {
|
||||
let x = number(cx, input, "x", true)?;
|
||||
let y = number(cx, input, "y", true)?;
|
||||
return Ok(NativeResult::Return(Value::Bool(
|
||||
x >= 0.0 && y >= 0.0 && x < geometry.width && y < geometry.height,
|
||||
)));
|
||||
}
|
||||
let node = block::snapshot(cx.store(), owner)?;
|
||||
let result = match self.query {
|
||||
Query::Measure => {
|
||||
@@ -208,16 +215,68 @@ impl NativeCallable for Method {
|
||||
vec![("commands", Value::Object(commands))],
|
||||
)?)
|
||||
}
|
||||
Query::HitTest => {
|
||||
let x = number(cx, input, "x", true)?;
|
||||
let y = number(cx, input, "y", true)?;
|
||||
Value::Bool(x >= 0.0 && y >= 0.0 && x < geometry.width && y < geometry.height)
|
||||
}
|
||||
Query::HitTest => unreachable!("handled above"),
|
||||
};
|
||||
Ok(NativeResult::Return(result))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PointMethod {
|
||||
expected: ObjectRef,
|
||||
circle: bool,
|
||||
}
|
||||
impl NativeCallable for PointMethod {
|
||||
fn invoke(&self, cx: &mut NativeContext<'_>, args: &[Value]) -> Result<NativeResult, VmError> {
|
||||
let Some(Value::Object(point)) = args.first() else {
|
||||
return Err(invalid("Point method requires a Point"));
|
||||
};
|
||||
if !cx.store().is_instance(*point, self.expected)? {
|
||||
return Err(invalid("Point method requires a Point"));
|
||||
}
|
||||
let x = number(cx, *point, "x", true)?;
|
||||
let y = number(cx, *point, "y", true)?;
|
||||
let inside = if self.circle {
|
||||
let [
|
||||
_,
|
||||
Value::Number(cx_value),
|
||||
Value::Number(cy_value),
|
||||
Value::Number(radius),
|
||||
] = args
|
||||
else {
|
||||
return Err(invalid("inCircle requires center x/y and radius"));
|
||||
};
|
||||
let parse = |value: &endor_core::EndorNumber| -> Result<f64, VmError> {
|
||||
let value = value
|
||||
.to_string()
|
||||
.parse::<f64>()
|
||||
.map_err(|_| invalid("invalid circle number"))?;
|
||||
if !value.is_finite() || value.abs() > MAX_DIMENSION {
|
||||
return Err(invalid("circle number exceeds bounds"));
|
||||
}
|
||||
Ok(value)
|
||||
};
|
||||
let dx = x as f64 - parse(cx_value)?;
|
||||
let dy = y as f64 - parse(cy_value)?;
|
||||
let radius = parse(radius)?;
|
||||
if radius < 0.0 {
|
||||
return Err(invalid("circle radius must be nonnegative"));
|
||||
}
|
||||
dx * dx + dy * dy <= radius * radius
|
||||
} else {
|
||||
let [_, Value::Object(bounds)] = args else {
|
||||
return Err(invalid("inside requires Bounds"));
|
||||
};
|
||||
let left = number(cx, *bounds, "x", true)?;
|
||||
let top = number(cx, *bounds, "y", true)?;
|
||||
let width = number(cx, *bounds, "width", false)?;
|
||||
let height = number(cx, *bounds, "height", false)?;
|
||||
x >= left && y >= top && x < left + width && y < top + height
|
||||
};
|
||||
Ok(NativeResult::Return(Value::Bool(inside)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn install(
|
||||
vm: &mut Vm,
|
||||
roots: &mut Vec<ObjectRef>,
|
||||
@@ -240,5 +299,23 @@ pub fn install(
|
||||
vm.attach_type(function, function_type)?;
|
||||
vm.define_method(block_type, name, function)?;
|
||||
}
|
||||
let registry = object(&vm.get_attr(desktop, "types")?)?;
|
||||
let point_type = object(
|
||||
&vm.dict_get(registry, &Value::Text("Point".into()))?
|
||||
.ok_or(invalid("missing Point type"))?,
|
||||
)?;
|
||||
for (name, circle) in [("inside", false), ("inCircle", true)] {
|
||||
let function = vm.allocate(ContextNativeFunction::new(
|
||||
name,
|
||||
PointMethod {
|
||||
expected: point_type,
|
||||
circle,
|
||||
},
|
||||
vec![point_type],
|
||||
))?;
|
||||
roots.push(function);
|
||||
vm.attach_type(function, function_type)?;
|
||||
vm.define_method(point_type, name, function)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user