diff --git a/Libraries/LibWeb/Internals/Internals.cpp b/Libraries/LibWeb/Internals/Internals.cpp index e1926eacdca..70c23046372 100644 --- a/Libraries/LibWeb/Internals/Internals.cpp +++ b/Libraries/LibWeb/Internals/Internals.cpp @@ -244,6 +244,11 @@ void Internals::set_echo_server_port(u16 const port) s_echo_server_port = port; } +void Internals::set_browser_zoom(double factor) +{ + internals_page().client().page_did_set_browser_zoom(factor); +} + bool Internals::headless() { return internals_page().client().is_headless(); diff --git a/Libraries/LibWeb/Internals/Internals.h b/Libraries/LibWeb/Internals/Internals.h index 037e6d4e284..709763e0dff 100644 --- a/Libraries/LibWeb/Internals/Internals.h +++ b/Libraries/LibWeb/Internals/Internals.h @@ -56,6 +56,8 @@ public: static u16 get_echo_server_port(); static void set_echo_server_port(u16 port); + void set_browser_zoom(double factor); + bool headless(); private: diff --git a/Libraries/LibWeb/Internals/Internals.idl b/Libraries/LibWeb/Internals/Internals.idl index 19f62a0f894..bdc411ec3bc 100644 --- a/Libraries/LibWeb/Internals/Internals.idl +++ b/Libraries/LibWeb/Internals/Internals.idl @@ -45,5 +45,7 @@ interface Internals { DOMString getComputedLabel(Element element); unsigned short getEchoServerPort(); + undefined setBrowserZoom(double factor); + readonly attribute boolean headless; }; diff --git a/Libraries/LibWeb/Page/Page.h b/Libraries/LibWeb/Page/Page.h index 48540e85318..e709527793b 100644 --- a/Libraries/LibWeb/Page/Page.h +++ b/Libraries/LibWeb/Page/Page.h @@ -384,6 +384,8 @@ public: virtual void page_did_finish_text_test([[maybe_unused]] String const& text) { } virtual void page_did_set_test_timeout([[maybe_unused]] double milliseconds) { } + virtual void page_did_set_browser_zoom([[maybe_unused]] double factor) { } + virtual void page_did_change_theme_color(Gfx::Color) { } virtual void page_did_insert_clipboard_entry([[maybe_unused]] String data, [[maybe_unused]] String presentation_style, [[maybe_unused]] String mime_type) { } diff --git a/Libraries/LibWebView/ViewImplementation.cpp b/Libraries/LibWebView/ViewImplementation.cpp index dd7467af858..a619274e0db 100644 --- a/Libraries/LibWebView/ViewImplementation.cpp +++ b/Libraries/LibWebView/ViewImplementation.cpp @@ -143,6 +143,12 @@ void ViewImplementation::zoom_out() update_zoom(); } +void ViewImplementation::set_zoom(double zoom_level) +{ + m_zoom_level = max(ZOOM_MIN_LEVEL, min(zoom_level, ZOOM_MAX_LEVEL)); + update_zoom(); +} + void ViewImplementation::reset_zoom() { m_zoom_level = 1.0f; diff --git a/Libraries/LibWebView/ViewImplementation.h b/Libraries/LibWebView/ViewImplementation.h index 08581a29eb7..46c91ca38a4 100644 --- a/Libraries/LibWebView/ViewImplementation.h +++ b/Libraries/LibWebView/ViewImplementation.h @@ -64,6 +64,7 @@ public: void zoom_in(); void zoom_out(); + void set_zoom(double zoom_level); void reset_zoom(); float zoom_level() const { return m_zoom_level; } float device_pixel_ratio() const { return m_device_pixel_ratio; } @@ -216,6 +217,7 @@ public: Function on_finish_handling_drag_event; Function on_text_test_finish; Function on_set_test_timeout; + Function on_set_browser_zoom; Function const& total_match_count)> on_find_in_page; Function on_theme_color_change; Function on_insert_clipboard_entry; diff --git a/Libraries/LibWebView/WebContentClient.cpp b/Libraries/LibWebView/WebContentClient.cpp index 19695eb47d0..8bfee313c22 100644 --- a/Libraries/LibWebView/WebContentClient.cpp +++ b/Libraries/LibWebView/WebContentClient.cpp @@ -101,6 +101,14 @@ void WebContentClient::did_set_test_timeout(u64 page_id, double milliseconds) } } +void WebContentClient::did_set_browser_zoom(u64 page_id, double factor) +{ + if (auto view = view_for_page_id(page_id); view.has_value()) { + if (view->on_set_browser_zoom) + view->on_set_browser_zoom(factor); + } +} + void WebContentClient::did_find_in_page(u64 page_id, size_t current_match_index, Optional const& total_match_count) { if (auto view = view_for_page_id(page_id); view.has_value()) { diff --git a/Libraries/LibWebView/WebContentClient.h b/Libraries/LibWebView/WebContentClient.h index 7983dea4b9f..acabd17b3da 100644 --- a/Libraries/LibWebView/WebContentClient.h +++ b/Libraries/LibWebView/WebContentClient.h @@ -109,6 +109,7 @@ private: virtual void did_finish_handling_input_event(u64 page_id, Web::EventResult event_result) override; virtual void did_finish_text_test(u64 page_id, String const& text) override; virtual void did_set_test_timeout(u64 page_id, double milliseconds) override; + virtual void did_set_browser_zoom(u64 page_id, double factor) override; virtual void did_find_in_page(u64 page_id, size_t current_match_index, Optional const& total_match_count) override; virtual void did_change_theme_color(u64 page_id, Gfx::Color color) override; virtual void did_insert_clipboard_entry(u64 page_id, String const& data, String const& presentation_style, String const& mime_type) override; diff --git a/Services/WebContent/PageClient.cpp b/Services/WebContent/PageClient.cpp index 2a76f117ab2..1b8adf3733d 100644 --- a/Services/WebContent/PageClient.cpp +++ b/Services/WebContent/PageClient.cpp @@ -229,6 +229,7 @@ void PageClient::set_viewport_size(Web::DevicePixelSize const& size) m_backing_store_manager.restart_resize_timer(); m_backing_store_manager.resize_backing_stores_if_needed(BackingStoreManager::WindowResizingInProgress::Yes); + m_pending_set_browser_zoom_request = false; } void PageClient::page_did_request_cursor_change(Gfx::StandardCursor cursor) @@ -371,6 +372,17 @@ void PageClient::page_did_set_test_timeout(double milliseconds) client().async_did_set_test_timeout(m_id, milliseconds); } +void PageClient::page_did_set_browser_zoom(double factor) +{ + m_pending_set_browser_zoom_request = true; + client().async_did_set_browser_zoom(m_id, factor); + + auto& event_loop = Web::HTML::main_thread_event_loop(); + event_loop.spin_until(GC::create_function(event_loop.heap(), [&]() { + return !m_pending_set_browser_zoom_request || !is_connection_open(); + })); +} + void PageClient::page_did_request_context_menu(Web::CSSPixelPoint content_position) { client().async_did_request_context_menu(m_id, page().css_to_device_point(content_position).to_type()); diff --git a/Services/WebContent/PageClient.h b/Services/WebContent/PageClient.h index f45b6c8c7f8..3a7418d8c40 100644 --- a/Services/WebContent/PageClient.h +++ b/Services/WebContent/PageClient.h @@ -159,6 +159,7 @@ private: virtual void page_did_request_select_dropdown(Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector items) override; virtual void page_did_finish_text_test(String const& text) override; virtual void page_did_set_test_timeout(double milliseconds) override; + virtual void page_did_set_browser_zoom(double factor) override; virtual void page_did_change_theme_color(Gfx::Color color) override; virtual void page_did_insert_clipboard_entry(String data, String presentation_style, String mime_type) override; virtual void page_did_change_audio_play_state(Web::HTML::AudioPlayState) override; @@ -215,6 +216,8 @@ private: GC::Root m_console_global_object; RefPtr m_paint_refresh_timer; + + bool m_pending_set_browser_zoom_request = false; }; } diff --git a/Services/WebContent/WebContentClient.ipc b/Services/WebContent/WebContentClient.ipc index ffd1eb0a3ac..f74ecf4f77b 100644 --- a/Services/WebContent/WebContentClient.ipc +++ b/Services/WebContent/WebContentClient.ipc @@ -97,6 +97,8 @@ endpoint WebContentClient did_finish_text_test(u64 page_id, String text) =| did_set_test_timeout(u64 page_id, double milliseconds) =| + did_set_browser_zoom(u64 page_id, double factor) =| + did_find_in_page(u64 page_id, size_t current_match_index, Optional total_match_count) =| request_worker_agent(u64 page_id) => (IPC::File socket) // FIXME: Add required attributes to select a SharedWorker Agent diff --git a/UI/AppKit/Interface/LadybirdWebView.mm b/UI/AppKit/Interface/LadybirdWebView.mm index 9d13f894489..64144c57c7b 100644 --- a/UI/AppKit/Interface/LadybirdWebView.mm +++ b/UI/AppKit/Interface/LadybirdWebView.mm @@ -958,6 +958,11 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_ [NSMenu popUpContextMenu:self.select_dropdown withEvent:event forView:self]; }; + m_web_view_bridge->on_set_browser_zoom = [](double factor) { + (void)factor; + dbgln("FIXME: A test called `window.internals.setBrowserZoom()` which is not implemented in the AppKit UI"); + }; + m_web_view_bridge->on_restore_window = [weak_self]() { LadybirdWebView* self = weak_self; if (self == nil) { diff --git a/UI/Headless/HeadlessWebView.cpp b/UI/Headless/HeadlessWebView.cpp index 7b46922bd52..81ef0ba2f74 100644 --- a/UI/Headless/HeadlessWebView.cpp +++ b/UI/Headless/HeadlessWebView.cpp @@ -191,4 +191,10 @@ void HeadlessWebView::on_test_complete(TestCompletion completion) m_test_promise->resolve(move(completion)); } +void HeadlessWebView::update_zoom() +{ + client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level); + client().async_set_viewport_size(m_client_state.page_index, m_viewport_size); +} + } diff --git a/UI/Headless/HeadlessWebView.h b/UI/Headless/HeadlessWebView.h index c15a614b1af..32eeb788b19 100644 --- a/UI/Headless/HeadlessWebView.h +++ b/UI/Headless/HeadlessWebView.h @@ -33,7 +33,7 @@ public: private: HeadlessWebView(Core::AnonymousBuffer theme, Web::DevicePixelSize viewport_size); - void update_zoom() override { } + void update_zoom() override; void initialize_client(CreateNewClient) override; virtual Web::DevicePixelSize viewport_size() const override { return m_viewport_size; } diff --git a/UI/Headless/Test.cpp b/UI/Headless/Test.cpp index 0ddd599a654..01e471a9420 100644 --- a/UI/Headless/Test.cpp +++ b/UI/Headless/Test.cpp @@ -140,6 +140,7 @@ void run_dump_test(HeadlessWebView& view, Test& test, URL::URL const& url, int t view.on_load_finish = {}; view.on_text_test_finish = {}; view.on_set_test_timeout = {}; + view.reset_zoom(); view.on_test_complete({ test, TestResult::Timeout }); }); @@ -199,6 +200,7 @@ void run_dump_test(HeadlessWebView& view, Test& test, URL::URL const& url, int t }; auto on_test_complete = [&view, &test, timer, handle_completed_test]() { + view.reset_zoom(); clear_test_callbacks(view); timer->stop(); @@ -268,6 +270,10 @@ void run_dump_test(HeadlessWebView& view, Test& test, URL::URL const& url, int t timer->start(milliseconds); }; + view.on_set_browser_zoom = [&view](double factor) { + view.set_zoom(factor); + }; + view.load(url); timer->start(); } @@ -278,6 +284,7 @@ static void run_ref_test(HeadlessWebView& view, Test& test, URL::URL const& url, view.on_load_finish = {}; view.on_text_test_finish = {}; view.on_set_test_timeout = {}; + view.reset_zoom(); view.on_test_complete({ test, TestResult::Timeout }); }); @@ -335,13 +342,15 @@ static void run_ref_test(HeadlessWebView& view, Test& test, URL::URL const& url, } else { test.ref_test_expectation_type = RefTestExpectationType::Match; } - view.take_screenshot()->when_resolved([&test, on_test_complete = move(on_test_complete)](RefPtr screenshot) { + view.take_screenshot()->when_resolved([&view, &test, on_test_complete = move(on_test_complete)](RefPtr screenshot) { test.expectation_screenshot = move(screenshot); + view.reset_zoom(); on_test_complete(); }); } else { view.take_screenshot()->when_resolved([&view, &test](RefPtr screenshot) { test.actual_screenshot = move(screenshot); + view.reset_zoom(); view.debug_request("load-reference-page"); }); } @@ -358,6 +367,10 @@ static void run_ref_test(HeadlessWebView& view, Test& test, URL::URL const& url, timer->start(milliseconds); }; + view.on_set_browser_zoom = [&view](double factor) { + view.set_zoom(factor); + }; + view.load(url); timer->start(); } diff --git a/UI/Qt/BrowserWindow.h b/UI/Qt/BrowserWindow.h index 30b418b9961..eafe0ca3cc5 100644 --- a/UI/Qt/BrowserWindow.h +++ b/UI/Qt/BrowserWindow.h @@ -133,6 +133,7 @@ public slots: void zoom_out(); void reset_zoom(); void update_zoom_menu(); + void update_displayed_zoom_level(); void select_all(); void show_find_in_page(); void paste(); @@ -154,7 +155,6 @@ private: void debug_request(ByteString const& request, ByteString const& argument = ""); void set_current_tab(Tab* tab); - void update_displayed_zoom_level(); template void for_each_tab(Callback&& callback) diff --git a/UI/Qt/WebContentView.cpp b/UI/Qt/WebContentView.cpp index 4d591b6065c..ae98bd594c9 100644 --- a/UI/Qt/WebContentView.cpp +++ b/UI/Qt/WebContentView.cpp @@ -164,6 +164,12 @@ WebContentView::WebContentView(QWidget* window, RefPtrexec(map_point_to_global_position(content_position)); }; + + on_set_browser_zoom = [this](double factor) { + set_zoom(factor); + auto* window = static_cast(this->window()); + window->update_displayed_zoom_level(); + }; } WebContentView::~WebContentView() = default;