Webdriver: Implement calculate the absolute position for Get Element Rect (#37847)

Implementing [calculate the absolute
position](https://w3c.github.io/webdriver/#dfn-calculate-the-absolute-position)
and make [Get Element
Rect](https://w3c.github.io/webdriver/#get-element-rect) conforms the
spec .

Testing: Covered in webdriver WPT, especially for pointer test that
needs to find the element rect.

Signed-off-by: PotatoCP <kenzieradityatirtarahardja18@gmail.com>
This commit is contained in:
Kenzie Raditya Tirtarahardja 2025-07-04 15:22:29 +08:00 committed by GitHub
parent 13eeb29878
commit a990ff82b9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 38 additions and 93 deletions

View file

@ -56,6 +56,7 @@ use crate::dom::bindings::reflector::{DomGlobal, DomObject};
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::document::Document; use crate::dom::document::Document;
use crate::dom::domrect::DOMRect;
use crate::dom::element::Element; use crate::dom::element::Element;
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
@ -1340,6 +1341,33 @@ pub(crate) fn handle_get_title(
.unwrap(); .unwrap();
} }
/// <https://w3c.github.io/webdriver/#dfn-calculate-the-absolute-position>
fn calculate_absolute_position(
documents: &DocumentCollection,
pipeline: &PipelineId,
rect: &DOMRect,
) -> Result<(f64, f64), ErrorStatus> {
// Step 1
// We already pass the rectangle here, see `handle_get_rect`.
// Step 2
let document = match documents.find_document(*pipeline) {
Some(document) => document,
None => return Err(ErrorStatus::UnknownError),
};
let win = match document.GetDefaultView() {
Some(win) => win,
None => return Err(ErrorStatus::UnknownError),
};
// Step 3 - 5
let x = win.ScrollX() as f64 + rect.X();
let y = win.ScrollY() as f64 + rect.Y();
Ok((x, y))
}
/// <https://w3c.github.io/webdriver/#get-element-rect>
pub(crate) fn handle_get_rect( pub(crate) fn handle_get_rect(
documents: &DocumentCollection, documents: &DocumentCollection,
pipeline: PipelineId, pipeline: PipelineId,
@ -1350,37 +1378,17 @@ pub(crate) fn handle_get_rect(
reply reply
.send( .send(
get_known_element(documents, pipeline, element_id).and_then(|element| { get_known_element(documents, pipeline, element_id).and_then(|element| {
// https://w3c.github.io/webdriver/webdriver-spec.html#dfn-calculate-the-absolute-position // Step 4-5
match element.downcast::<HTMLElement>() { // We pass the rect instead of element so we don't have to
Some(html_element) => { // call `GetBoundingClientRect` twice.
// Step 1 let rect = element.GetBoundingClientRect(can_gc);
let mut x = 0; let (x, y) = calculate_absolute_position(documents, &pipeline, &rect)?;
let mut y = 0;
let mut offset_parent = html_element.GetOffsetParent(can_gc); // Step 6-7
// Step 2
while let Some(element) = offset_parent {
offset_parent = match element.downcast::<HTMLElement>() {
Some(elem) => {
x += elem.OffsetLeft(can_gc);
y += elem.OffsetTop(can_gc);
elem.GetOffsetParent(can_gc)
},
None => None,
};
}
// Step 3
Ok(Rect::new( Ok(Rect::new(
Point2D::new(x as f64, y as f64), Point2D::new(x, y),
Size2D::new( Size2D::new(rect.Width(), rect.Height()),
html_element.OffsetWidth(can_gc) as f64,
html_element.OffsetHeight(can_gc) as f64,
),
)) ))
},
None => Err(ErrorStatus::UnknownError),
}
}), }),
) )
.unwrap(); .unwrap();

View file

@ -1,6 +1,3 @@
[get.py] [get.py]
[test_no_browsing_context] [test_no_browsing_context]
expected: FAIL expected: FAIL
[test_basic]
expected: FAIL

View file

@ -1,58 +1,4 @@
[pointer_mouse_drag.py] [pointer_mouse_drag.py]
[test_drag_and_drop[20-0-0\]]
expected: FAIL
[test_drag_and_drop[20-0-300\]]
expected: FAIL
[test_drag_and_drop[20-0-800\]]
expected: FAIL
[test_drag_and_drop[0-15-0\]]
expected: FAIL
[test_drag_and_drop[0-15-300\]]
expected: FAIL
[test_drag_and_drop[0-15-800\]]
expected: FAIL
[test_drag_and_drop[10-15-0\]]
expected: FAIL
[test_drag_and_drop[10-15-300\]]
expected: FAIL
[test_drag_and_drop[10-15-800\]]
expected: FAIL
[test_drag_and_drop[-20-0-0\]]
expected: FAIL
[test_drag_and_drop[-20-0-300\]]
expected: FAIL
[test_drag_and_drop[-20-0-800\]]
expected: FAIL
[test_drag_and_drop[10--15-0\]]
expected: FAIL
[test_drag_and_drop[10--15-300\]]
expected: FAIL
[test_drag_and_drop[10--15-800\]]
expected: FAIL
[test_drag_and_drop[-10--15-0\]]
expected: FAIL
[test_drag_and_drop[-10--15-300\]]
expected: FAIL
[test_drag_and_drop[-10--15-800\]]
expected: FAIL
[test_drag_and_drop_with_draggable_element[0\]] [test_drag_and_drop_with_draggable_element[0\]]
expected: FAIL expected: FAIL

View file

@ -5,8 +5,5 @@
[test_element_center_point_with_offset] [test_element_center_point_with_offset]
expected: FAIL expected: FAIL
[test_element_in_view_center_point_partly_visible]
expected: FAIL
[test_element_larger_than_viewport] [test_element_larger_than_viewport]
expected: FAIL expected: FAIL

View file

@ -1,6 +1,3 @@
[pointer_pause_dblclick.py] [pointer_pause_dblclick.py]
[test_dblclick_with_pause_after_second_pointerdown] [test_dblclick_with_pause_after_second_pointerdown]
expected: FAIL expected: FAIL
[test_no_dblclick]
expected: FAIL