mirror of
https://github.com/servo/servo.git
synced 2025-08-12 08:55:32 +01:00
script: When using WebRender, keep the DOM-side scroll positions for
elements with `overflow: scroll` up to date, and take them into account when doing hit testing. Closes #11648.
This commit is contained in:
parent
ce88b8ed30
commit
041cfe6d0a
14 changed files with 259 additions and 47 deletions
|
@ -487,14 +487,15 @@ impl DisplayList {
|
|||
/// Places all nodes containing the point of interest into `result`, topmost first. Respects
|
||||
/// the `pointer-events` CSS property If `topmost_only` is true, stops after placing one node
|
||||
/// into the list. `result` must be empty upon entry to this function.
|
||||
pub fn hit_test(&self, point: Point2D<Au>) -> Vec<DisplayItemMetadata> {
|
||||
pub fn hit_test(&self, point: &Point2D<Au>, scroll_offsets: &ScrollOffsetMap)
|
||||
-> Vec<DisplayItemMetadata> {
|
||||
let mut traversal = DisplayListTraversal {
|
||||
display_list: self,
|
||||
current_item_index: 0,
|
||||
last_item_index: self.list.len() - 1,
|
||||
};
|
||||
let mut result = Vec::new();
|
||||
self.root_stacking_context.hit_test(&mut traversal, point, &mut result);
|
||||
self.root_stacking_context.hit_test(&mut traversal, point, scroll_offsets, &mut result);
|
||||
result.reverse();
|
||||
result
|
||||
}
|
||||
|
@ -610,24 +611,38 @@ impl StackingContext {
|
|||
|
||||
pub fn hit_test<'a>(&self,
|
||||
traversal: &mut DisplayListTraversal<'a>,
|
||||
point: Point2D<Au>,
|
||||
point: &Point2D<Au>,
|
||||
scroll_offsets: &ScrollOffsetMap,
|
||||
result: &mut Vec<DisplayItemMetadata>) {
|
||||
// Convert the point into stacking context local space
|
||||
let point = if self.context_type == StackingContextType::Real {
|
||||
let point = point - self.bounds.origin;
|
||||
// Convert the point into stacking context local transform space.
|
||||
let mut point = if self.context_type == StackingContextType::Real {
|
||||
let point = *point - self.bounds.origin;
|
||||
let inv_transform = self.transform.invert();
|
||||
let frac_point = inv_transform.transform_point(&Point2D::new(point.x.to_f32_px(),
|
||||
point.y.to_f32_px()));
|
||||
Point2D::new(Au::from_f32_px(frac_point.x), Au::from_f32_px(frac_point.y))
|
||||
} else {
|
||||
point
|
||||
*point
|
||||
};
|
||||
|
||||
// Adjust the point to account for the scroll offset if necessary. This can only happen
|
||||
// when WebRender is in use.
|
||||
//
|
||||
// We don't perform this adjustment on the root stacking context because the DOM-side code
|
||||
// has already translated the point for us (e.g. in `Document::handle_mouse_move_event()`)
|
||||
// by now.
|
||||
if self.id != StackingContextId::root() {
|
||||
if let Some(scroll_offset) = scroll_offsets.get(&self.id) {
|
||||
point.x -= Au::from_f32_px(scroll_offset.x);
|
||||
point.y -= Au::from_f32_px(scroll_offset.y);
|
||||
}
|
||||
}
|
||||
|
||||
for child in self.children.iter() {
|
||||
while let Some(item) = traversal.advance(self) {
|
||||
item.hit_test(point, result);
|
||||
}
|
||||
child.hit_test(traversal, point, result);
|
||||
child.hit_test(traversal, &point, scroll_offsets, result);
|
||||
}
|
||||
|
||||
while let Some(item) = traversal.advance(self) {
|
||||
|
@ -1415,3 +1430,7 @@ impl WebRenderImageInfo {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of the scroll offset list. This is only populated if WebRender is in use.
|
||||
pub type ScrollOffsetMap = HashMap<StackingContextId, Point2D<f32>>;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue