mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
auto merge of #3538 : mrobinson/servo/events-and-layers, r=zwarich
Select the topmost layer at a given point to send mouse events and when sending the event, ensure that they are relative to the layer origin, rather than in absolute page coordinates. Fixes #3504.
This commit is contained in:
commit
479d8567d1
1 changed files with 46 additions and 19 deletions
|
@ -139,36 +139,63 @@ fn scroll_layer_and_all_child_layers(layer: Rc<Layer<CompositorData>>,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct HitTestResult {
|
||||||
|
layer: Rc<Layer<CompositorData>>,
|
||||||
|
point: TypedPoint2D<LayerPixel, f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_topmost_layer_at_point(layer: Rc<Layer<CompositorData>>,
|
||||||
|
point: TypedPoint2D<LayerPixel, f32>)
|
||||||
|
-> Option<HitTestResult> {
|
||||||
|
let child_point = point - layer.bounds.borrow().origin;
|
||||||
|
for child in layer.children().iter().rev() {
|
||||||
|
let result = find_topmost_layer_at_point(child.clone(), child_point);
|
||||||
|
if result.is_some() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let point = point - *layer.content_offset.borrow();
|
||||||
|
if !layer.bounds.borrow().contains(&point) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(HitTestResult { layer: layer, point: point });
|
||||||
|
}
|
||||||
|
|
||||||
// Takes in a MouseWindowEvent, determines if it should be passed to children, and
|
// Takes in a MouseWindowEvent, determines if it should be passed to children, and
|
||||||
// sends the event off to the appropriate pipeline. NB: the cursor position is in
|
// sends the event off to the appropriate pipeline. NB: the cursor position is in
|
||||||
// page coordinates.
|
// page coordinates.
|
||||||
pub fn send_mouse_event(layer: Rc<Layer<CompositorData>>,
|
pub fn send_mouse_event(layer: Rc<Layer<CompositorData>>,
|
||||||
event: MouseWindowEvent,
|
event: MouseWindowEvent,
|
||||||
cursor: TypedPoint2D<LayerPixel, f32>) {
|
cursor: TypedPoint2D<LayerPixel, f32>) {
|
||||||
let content_offset = *layer.content_offset.borrow();
|
match find_topmost_layer_at_point(layer.clone(), cursor) {
|
||||||
let cursor = cursor - content_offset;
|
Some(result) => {
|
||||||
for child in layer.children().iter() {
|
let event_point = result.point.to_untyped();
|
||||||
let child_bounds = child.bounds.borrow();
|
let message = match event {
|
||||||
if child_bounds.contains(&cursor) {
|
MouseWindowClickEvent(button, _) => ClickEvent(button, event_point),
|
||||||
send_mouse_event(child.clone(), event, cursor - child_bounds.origin);
|
MouseWindowMouseDownEvent(button, _) => MouseDownEvent(button, event_point),
|
||||||
return;
|
MouseWindowMouseUpEvent(button, _) => MouseUpEvent(button, event_point),
|
||||||
}
|
};
|
||||||
|
let pipeline = &result.layer.extra_data.borrow().pipeline;
|
||||||
|
let ScriptControlChan(ref chan) = pipeline.script_chan;
|
||||||
|
let _ = chan.send_opt(SendEventMsg(pipeline.id.clone(), message));
|
||||||
|
},
|
||||||
|
None => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// This mouse event is mine!
|
|
||||||
let message = match event {
|
|
||||||
MouseWindowClickEvent(button, _) => ClickEvent(button, cursor.to_untyped()),
|
|
||||||
MouseWindowMouseDownEvent(button, _) => MouseDownEvent(button, cursor.to_untyped()),
|
|
||||||
MouseWindowMouseUpEvent(button, _) => MouseUpEvent(button, cursor.to_untyped()),
|
|
||||||
};
|
|
||||||
let ScriptControlChan(ref chan) = layer.extra_data.borrow().pipeline.script_chan;
|
|
||||||
let _ = chan.send_opt(SendEventMsg(layer.extra_data.borrow().pipeline.id.clone(), message));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_mouse_move_event(layer: Rc<Layer<CompositorData>>,
|
pub fn send_mouse_move_event(layer: Rc<Layer<CompositorData>>,
|
||||||
cursor: TypedPoint2D<LayerPixel, f32>) {
|
cursor: TypedPoint2D<LayerPixel, f32>) {
|
||||||
let message = MouseMoveEvent(cursor.to_untyped());
|
match find_topmost_layer_at_point(layer.clone(), cursor) {
|
||||||
let ScriptControlChan(ref chan) = layer.extra_data.borrow().pipeline.script_chan;
|
Some(result) => {
|
||||||
let _ = chan.send_opt(SendEventMsg(layer.extra_data.borrow().pipeline.id.clone(), message));
|
let message = MouseMoveEvent(result.point.to_untyped());
|
||||||
|
let pipeline = &result.layer.extra_data.borrow().pipeline;
|
||||||
|
let ScriptControlChan(ref chan) = pipeline.script_chan;
|
||||||
|
let _ = chan.send_opt(SendEventMsg(pipeline.id.clone(), message));
|
||||||
|
},
|
||||||
|
None => {},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue