From c93c30d59669470d5310307d45143e149fe73196 Mon Sep 17 00:00:00 2001 From: Luke Wilde Date: Fri, 25 Jul 2025 13:10:00 +0100 Subject: [PATCH] LibWebView+WebContent: Make it possible to change the painting interval This allows us to paint at the refresh rate of the screen. The default is 60, as before, in case it never gets set by anything. --- Libraries/LibWebView/ViewImplementation.cpp | 1 + Libraries/LibWebView/ViewImplementation.h | 2 ++ Services/WebContent/ConnectionFromClient.cpp | 6 ++++++ Services/WebContent/ConnectionFromClient.h | 1 + Services/WebContent/PageClient.cpp | 19 ++++++++++++++++++- Services/WebContent/PageClient.h | 2 ++ Services/WebContent/WebContentServer.ipc | 1 + 7 files changed, 31 insertions(+), 1 deletion(-) diff --git a/Libraries/LibWebView/ViewImplementation.cpp b/Libraries/LibWebView/ViewImplementation.cpp index 02b4ba751ac..3b9586405df 100644 --- a/Libraries/LibWebView/ViewImplementation.cpp +++ b/Libraries/LibWebView/ViewImplementation.cpp @@ -589,6 +589,7 @@ void ViewImplementation::initialize_client(CreateNewClient create_new_client) client().async_set_window_handle(m_client_state.page_index, m_client_state.client_handle); client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio); + client().async_set_maximum_frames_per_second(m_client_state.page_index, m_maximum_frames_per_second); client().async_set_system_visibility_state(m_client_state.page_index, m_system_visibility_state); if (auto webdriver_content_ipc_path = Application::browser_options().webdriver_content_ipc_path; webdriver_content_ipc_path.has_value()) diff --git a/Libraries/LibWebView/ViewImplementation.h b/Libraries/LibWebView/ViewImplementation.h index a887fc11f18..e76b064ad66 100644 --- a/Libraries/LibWebView/ViewImplementation.h +++ b/Libraries/LibWebView/ViewImplementation.h @@ -72,6 +72,7 @@ public: void reset_zoom(); float zoom_level() const { return m_zoom_level; } float device_pixel_ratio() const { return m_device_pixel_ratio; } + double maximum_frames_per_second() const { return m_maximum_frames_per_second; } void enqueue_input_event(Web::InputEvent); void did_finish_handling_input_event(Badge, Web::EventResult event_result); @@ -288,6 +289,7 @@ protected: float m_zoom_level { 1.0 }; float m_device_pixel_ratio { 1.0 }; + double m_maximum_frames_per_second { 60.0 }; Queue m_pending_input_events; diff --git a/Services/WebContent/ConnectionFromClient.cpp b/Services/WebContent/ConnectionFromClient.cpp index fb41343ee73..70c84ee9f1e 100644 --- a/Services/WebContent/ConnectionFromClient.cpp +++ b/Services/WebContent/ConnectionFromClient.cpp @@ -1158,6 +1158,12 @@ void ConnectionFromClient::set_device_pixels_per_css_pixel(u64 page_id, float de page->set_device_pixels_per_css_pixel(device_pixels_per_css_pixel); } +void ConnectionFromClient::set_maximum_frames_per_second(u64 page_id, double maximum_frames_per_second) +{ + if (auto page = this->page(page_id); page.has_value()) + page->set_maximum_frames_per_second(maximum_frames_per_second); +} + void ConnectionFromClient::set_window_position(u64 page_id, Web::DevicePixelPoint position) { if (auto page = this->page(page_id); page.has_value()) diff --git a/Services/WebContent/ConnectionFromClient.h b/Services/WebContent/ConnectionFromClient.h index 4b636395dd9..2d3c334e7f1 100644 --- a/Services/WebContent/ConnectionFromClient.h +++ b/Services/WebContent/ConnectionFromClient.h @@ -112,6 +112,7 @@ private: virtual void set_has_focus(u64 page_id, bool) override; virtual void set_is_scripting_enabled(u64 page_id, bool) override; virtual void set_device_pixels_per_css_pixel(u64 page_id, float) override; + virtual void set_maximum_frames_per_second(u64 page_id, double) override; virtual void set_window_position(u64 page_id, Web::DevicePixelPoint) override; virtual void set_window_size(u64 page_id, Web::DevicePixelSize) override; virtual void did_update_window_rect(u64 page_id) override; diff --git a/Services/WebContent/PageClient.cpp b/Services/WebContent/PageClient.cpp index f6975a70cf6..409513908cf 100644 --- a/Services/WebContent/PageClient.cpp +++ b/Services/WebContent/PageClient.cpp @@ -68,7 +68,11 @@ PageClient::PageClient(PageHost& owner, u64 id) { setup_palette(); - int refresh_interval = 1000 / 60; // FIXME: Account for the actual refresh rate of the display + // FIXME: This removes the decimal part, so the refresh interval will actually be higher than the maximum FPS. + // For example, 60 FPS = 1000ms / 60 = 16.6666...ms, but it will become 16ms, making the interval equivalent + // to 62.5 FPS. + int refresh_interval = static_cast(1000.0 / m_maximum_frames_per_second); + m_paint_refresh_timer = Core::Timer::create_repeating(refresh_interval, [] { Web::HTML::main_thread_event_loop().queue_task_to_update_the_rendering(); }); @@ -202,6 +206,19 @@ void PageClient::set_viewport_size(Web::DevicePixelSize const& size) page().top_level_traversable()->set_viewport_size(page().device_to_css_size(size)); } +void PageClient::set_maximum_frames_per_second(u64 maximum_frames_per_second) +{ + m_maximum_frames_per_second = maximum_frames_per_second; + + // FIXME: This removes the decimal part, so the refresh interval will actually be higher than the maximum FPS. + // For example, 60 FPS = 1000ms / 60 = 16.6666...ms, but it will become 16ms, making the interval equivalent + // to 62.5 FPS. + int refresh_interval = static_cast(1000.0 / m_maximum_frames_per_second); + + VERIFY(m_paint_refresh_timer); + m_paint_refresh_timer->set_interval(refresh_interval); +} + void PageClient::page_did_request_cursor_change(Gfx::Cursor const& cursor) { client().async_did_request_cursor_change(m_id, cursor); diff --git a/Services/WebContent/PageClient.h b/Services/WebContent/PageClient.h index 6f40269cbcb..242ec0d48fd 100644 --- a/Services/WebContent/PageClient.h +++ b/Services/WebContent/PageClient.h @@ -55,6 +55,7 @@ public: void set_viewport_size(Web::DevicePixelSize const&); void set_screen_rects(Vector const& rects, size_t main_screen_index) { m_screen_rect = rects[main_screen_index]; } void set_device_pixels_per_css_pixel(float device_pixels_per_css_pixel) { m_device_pixels_per_css_pixel = device_pixels_per_css_pixel; } + void set_maximum_frames_per_second(u64 maximum_frames_per_second); void set_preferred_color_scheme(Web::CSS::PreferredColorScheme); void set_preferred_contrast(Web::CSS::PreferredContrast); void set_preferred_motion(Web::CSS::PreferredMotion); @@ -186,6 +187,7 @@ private: RefPtr m_palette_impl; Web::DevicePixelRect m_screen_rect; float m_device_pixels_per_css_pixel { 1.0f }; + double m_maximum_frames_per_second { 60.0 }; u64 m_id { 0 }; bool m_has_focus { false }; diff --git a/Services/WebContent/WebContentServer.ipc b/Services/WebContent/WebContentServer.ipc index ab0e9d6f5f7..e7b6e2e6402 100644 --- a/Services/WebContent/WebContentServer.ipc +++ b/Services/WebContent/WebContentServer.ipc @@ -99,6 +99,7 @@ endpoint WebContentServer set_has_focus(u64 page_id, bool has_focus) =| set_is_scripting_enabled(u64 page_id, bool is_scripting_enabled) =| set_device_pixels_per_css_pixel(u64 page_id, float device_pixels_per_css_pixel) =| + set_maximum_frames_per_second(u64 page_id, double maximum_frames_per_second) =| set_window_position(u64 page_id, Web::DevicePixelPoint position) =| set_window_size(u64 page_id, Web::DevicePixelSize size) =|