From 995f3db3848b9f6b6661b0738b7308d925147c50 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Thu, 3 Nov 2022 12:51:44 -0400 Subject: [PATCH] LibWebView+WebConent: Add an IPC to get an element's absolute rect --- .../LibWebView/OutOfProcessWebView.cpp | 5 +++ .../LibWebView/OutOfProcessWebView.h | 1 + .../WebContent/ConnectionFromClient.cpp | 31 +++++++++++++++++++ .../WebContent/ConnectionFromClient.h | 1 + .../Services/WebContent/WebContentServer.ipc | 2 ++ 5 files changed, 40 insertions(+) diff --git a/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp b/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp index 59e4ece8759..151ba6f264f 100644 --- a/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp +++ b/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp @@ -560,6 +560,11 @@ String OutOfProcessWebView::get_element_tag_name(i32 element_id) return client().get_element_tag_name(element_id); } +Gfx::IntRect OutOfProcessWebView::get_element_rect(i32 element_id) +{ + return client().get_element_rect(element_id); +} + void OutOfProcessWebView::set_content_filters(Vector filters) { client().async_set_content_filters(filters); diff --git a/Userland/Libraries/LibWebView/OutOfProcessWebView.h b/Userland/Libraries/LibWebView/OutOfProcessWebView.h index eb95879329b..6b8b90a14ac 100644 --- a/Userland/Libraries/LibWebView/OutOfProcessWebView.h +++ b/Userland/Libraries/LibWebView/OutOfProcessWebView.h @@ -71,6 +71,7 @@ public: String get_computed_value_for_element(i32 element_id, String const& property_name); String get_element_text(i32 element_id); String get_element_tag_name(i32 element_id); + Gfx::IntRect get_element_rect(i32 element_id); void set_content_filters(Vector); void set_proxy_mappings(Vector proxies, HashMap mappings); diff --git a/Userland/Services/WebContent/ConnectionFromClient.cpp b/Userland/Services/WebContent/ConnectionFromClient.cpp index 38f9211276a..7f38ef8e7df 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.cpp +++ b/Userland/Services/WebContent/ConnectionFromClient.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -585,6 +586,36 @@ Messages::WebContentServer::GetElementTagNameResponse ConnectionFromClient::get_ return { element->tag_name() }; } +// https://w3c.github.io/webdriver/#dfn-calculate-the-absolute-position +static Gfx::IntPoint calculate_absolute_position_of_element(Web::Page const& page, JS::NonnullGCPtr rect) +{ + // 1. Let rect be the value returned by calling getBoundingClientRect(). + + // 2. Let window be the associated window of current top-level browsing context. + auto const* window = page.top_level_browsing_context().active_window(); + + // 3. Let x be (scrollX of window + rect’s x coordinate). + auto x = (window ? static_cast(window->scroll_x()) : 0) + static_cast(rect->x()); + + // 4. Let y be (scrollY of window + rect’s y coordinate). + auto y = (window ? static_cast(window->scroll_y()) : 0) + static_cast(rect->y()); + + // 5. Return a pair of (x, y). + return { x, y }; +} + +Messages::WebContentServer::GetElementRectResponse ConnectionFromClient::get_element_rect(i32 element_id) +{ + auto element = find_element_by_id(element_id); + if (!element.has_value()) + return { {} }; + + auto bounding_rect = element->get_bounding_client_rect(); + auto coordinates = calculate_absolute_position_of_element(page(), bounding_rect); + + return { { coordinates.x(), coordinates.y(), static_cast(bounding_rect->width()), static_cast(bounding_rect->height()) } }; +} + Messages::WebContentServer::GetSelectedTextResponse ConnectionFromClient::get_selected_text() { return page().focused_context().selected_text(); diff --git a/Userland/Services/WebContent/ConnectionFromClient.h b/Userland/Services/WebContent/ConnectionFromClient.h index 3edf6cf432d..b1b23efb26f 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.h +++ b/Userland/Services/WebContent/ConnectionFromClient.h @@ -90,6 +90,7 @@ private: virtual Messages::WebContentServer::GetComputedValueForElementResponse get_computed_value_for_element(i32 element_id, String const& property_name) override; virtual Messages::WebContentServer::GetElementTextResponse get_element_text(i32 element_id) override; virtual Messages::WebContentServer::GetElementTagNameResponse get_element_tag_name(i32 element_id) override; + virtual Messages::WebContentServer::GetElementRectResponse get_element_rect(i32 element_id) override; virtual Messages::WebContentServer::GetLocalStorageEntriesResponse get_local_storage_entries() override; virtual Messages::WebContentServer::GetSessionStorageEntriesResponse get_session_storage_entries() override; diff --git a/Userland/Services/WebContent/WebContentServer.ipc b/Userland/Services/WebContent/WebContentServer.ipc index db011480a05..e943d6cd516 100644 --- a/Userland/Services/WebContent/WebContentServer.ipc +++ b/Userland/Services/WebContent/WebContentServer.ipc @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ endpoint WebContentServer get_computed_value_for_element(i32 element_id, String property_name) => (String computed_value) get_element_text(i32 element_id) => (String text) get_element_tag_name(i32 element_id) => (String tag_name) + get_element_rect(i32 element_id) => (Gfx::IntRect rect) webdriver_execute_script(String body, Vector json_arguments, Optional timeout, bool async) => (Web::WebDriver::ExecuteScriptResultType result_type, String json_result)