UI/Qt: Set WC's max FPS to the refresh rate of the current screen

This commit is contained in:
Luke Wilde 2025-07-25 16:43:27 +01:00 committed by Alexander Kalenik
commit 124bdce99c
Notes: github-actions[bot] 2025-07-26 14:10:29 +00:00
5 changed files with 40 additions and 4 deletions

View file

@ -82,18 +82,26 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, IsPopupWindow
// Listen for DPI changes // Listen for DPI changes
m_device_pixel_ratio = devicePixelRatio(); m_device_pixel_ratio = devicePixelRatio();
m_current_screen = screen(); m_current_screen = screen();
m_refresh_rate = m_current_screen->refreshRate();
if (QT_VERSION < QT_VERSION_CHECK(6, 6, 0) || QGuiApplication::platformName() != "wayland") { if (QT_VERSION < QT_VERSION_CHECK(6, 6, 0) || QGuiApplication::platformName() != "wayland") {
setAttribute(Qt::WA_NativeWindow); setAttribute(Qt::WA_NativeWindow);
setAttribute(Qt::WA_DontCreateNativeAncestors); setAttribute(Qt::WA_DontCreateNativeAncestors);
QObject::connect(m_current_screen, &QScreen::logicalDotsPerInchChanged, this, &BrowserWindow::device_pixel_ratio_changed); QObject::connect(m_current_screen, &QScreen::logicalDotsPerInchChanged, this, &BrowserWindow::device_pixel_ratio_changed);
QObject::connect(m_current_screen, &QScreen::refreshRateChanged, this, &BrowserWindow::refresh_rate_changed);
QObject::connect(windowHandle(), &QWindow::screenChanged, this, [this](QScreen* screen) { QObject::connect(windowHandle(), &QWindow::screenChanged, this, [this](QScreen* screen) {
if (m_device_pixel_ratio != devicePixelRatio()) if (m_device_pixel_ratio != devicePixelRatio())
device_pixel_ratio_changed(devicePixelRatio()); device_pixel_ratio_changed(devicePixelRatio());
// Listen for logicalDotsPerInchChanged signals on new screen if (m_refresh_rate != screen->refreshRate())
refresh_rate_changed(screen->refreshRate());
// Listen for logicalDotsPerInchChanged and refreshRateChanged signals on new screen
QObject::disconnect(m_current_screen, &QScreen::logicalDotsPerInchChanged, nullptr, nullptr); QObject::disconnect(m_current_screen, &QScreen::logicalDotsPerInchChanged, nullptr, nullptr);
QObject::disconnect(m_current_screen, &QScreen::refreshRateChanged, nullptr, nullptr);
m_current_screen = screen; m_current_screen = screen;
QObject::connect(m_current_screen, &QScreen::logicalDotsPerInchChanged, this, &BrowserWindow::device_pixel_ratio_changed); QObject::connect(m_current_screen, &QScreen::logicalDotsPerInchChanged, this, &BrowserWindow::device_pixel_ratio_changed);
QObject::connect(m_current_screen, &QScreen::refreshRateChanged, this, &BrowserWindow::refresh_rate_changed);
}); });
} }
@ -893,6 +901,14 @@ void BrowserWindow::device_pixel_ratio_changed(qreal dpi)
}); });
} }
void BrowserWindow::refresh_rate_changed(qreal refresh_rate)
{
m_refresh_rate = refresh_rate;
for_each_tab([this](auto& tab) {
tab.view().set_maximum_frames_per_second(m_refresh_rate);
});
}
void BrowserWindow::tab_title_changed(int index, QString const& title) void BrowserWindow::tab_title_changed(int index, QString const& title)
{ {
// NOTE: Qt uses ampersands for shortcut keys in tab titles, so we need to escape them. // NOTE: Qt uses ampersands for shortcut keys in tab titles, so we need to escape them.

View file

@ -100,8 +100,11 @@ public:
Tab* current_tab() const { return m_current_tab; } Tab* current_tab() const { return m_current_tab; }
double refresh_rate() const { return m_refresh_rate; }
public slots: public slots:
void device_pixel_ratio_changed(qreal dpi); void device_pixel_ratio_changed(qreal dpi);
void refresh_rate_changed(qreal refresh_rate);
void tab_title_changed(int index, QString const&); void tab_title_changed(int index, QString const&);
void tab_favicon_changed(int index, QIcon const& icon); void tab_favicon_changed(int index, QIcon const& icon);
void tab_audio_play_state_changed(int index, Web::HTML::AudioPlayState); void tab_audio_play_state_changed(int index, Web::HTML::AudioPlayState);
@ -174,6 +177,7 @@ private:
QScreen* m_current_screen; QScreen* m_current_screen;
double m_device_pixel_ratio { 0 }; double m_device_pixel_ratio { 0 };
double m_refresh_rate { 60.0 };
Web::CSS::PreferredColorScheme m_preferred_color_scheme; Web::CSS::PreferredColorScheme m_preferred_color_scheme;
void set_preferred_color_scheme(Web::CSS::PreferredColorScheme color_scheme); void set_preferred_color_scheme(Web::CSS::PreferredColorScheme color_scheme);

View file

@ -56,7 +56,11 @@ Tab::Tab(BrowserWindow* window, RefPtr<WebView::WebContentClient> parent_client,
m_layout->setSpacing(0); m_layout->setSpacing(0);
m_layout->setContentsMargins(0, 0, 0, 0); m_layout->setContentsMargins(0, 0, 0, 0);
m_view = new WebContentView(this, parent_client, page_index); auto view_initial_state = WebContentViewInitialState {
.maximum_frames_per_second = window->refresh_rate(),
};
m_view = new WebContentView(this, parent_client, page_index, AK::move(view_initial_state));
m_find_in_page = new FindInPageWidget(this, m_view); m_find_in_page = new FindInPageWidget(this, m_view);
m_find_in_page->setVisible(false); m_find_in_page->setVisible(false);
m_toolbar = new QToolBar(this); m_toolbar = new QToolBar(this);

View file

@ -47,7 +47,7 @@ namespace Ladybird {
bool is_using_dark_system_theme(QWidget&); bool is_using_dark_system_theme(QWidget&);
WebContentView::WebContentView(QWidget* window, RefPtr<WebView::WebContentClient> parent_client, size_t page_index) WebContentView::WebContentView(QWidget* window, RefPtr<WebView::WebContentClient> parent_client, size_t page_index, WebContentViewInitialState initial_state)
: QWidget(window) : QWidget(window)
{ {
m_client_state.client = parent_client; m_client_state.client = parent_client;
@ -60,6 +60,7 @@ WebContentView::WebContentView(QWidget* window, RefPtr<WebView::WebContentClient
setFocusPolicy(Qt::FocusPolicy::StrongFocus); setFocusPolicy(Qt::FocusPolicy::StrongFocus);
m_device_pixel_ratio = devicePixelRatio(); m_device_pixel_ratio = devicePixelRatio();
m_maximum_frames_per_second = initial_state.maximum_frames_per_second;
QObject::connect(qGuiApp, &QGuiApplication::screenRemoved, [this](QScreen*) { QObject::connect(qGuiApp, &QGuiApplication::screenRemoved, [this](QScreen*) {
update_screen_rects(); update_screen_rects();
@ -538,6 +539,12 @@ void WebContentView::set_device_pixel_ratio(double device_pixel_ratio)
handle_resize(); handle_resize();
} }
void WebContentView::set_maximum_frames_per_second(double maximum_frames_per_second)
{
m_maximum_frames_per_second = maximum_frames_per_second;
client().async_set_maximum_frames_per_second(m_client_state.page_index, m_maximum_frames_per_second);
}
void WebContentView::update_viewport_size() void WebContentView::update_viewport_size()
{ {
auto scaled_width = int(width() * m_device_pixel_ratio); auto scaled_width = int(width() * m_device_pixel_ratio);

View file

@ -43,12 +43,16 @@ namespace Ladybird {
class Tab; class Tab;
struct WebContentViewInitialState {
double maximum_frames_per_second { 60.0 };
};
class WebContentView final class WebContentView final
: public QWidget : public QWidget
, public WebView::ViewImplementation { , public WebView::ViewImplementation {
Q_OBJECT Q_OBJECT
public: public:
WebContentView(QWidget* window, RefPtr<WebView::WebContentClient> parent_client = nullptr, size_t page_index = 0); WebContentView(QWidget* window, RefPtr<WebView::WebContentClient> parent_client = nullptr, size_t page_index = 0, WebContentViewInitialState initial_state = {});
virtual ~WebContentView() override; virtual ~WebContentView() override;
Function<String(const URL::URL&, Web::HTML::ActivateTab)> on_tab_open_request; Function<String(const URL::URL&, Web::HTML::ActivateTab)> on_tab_open_request;
@ -76,6 +80,7 @@ public:
void set_viewport_rect(Gfx::IntRect); void set_viewport_rect(Gfx::IntRect);
void set_device_pixel_ratio(double); void set_device_pixel_ratio(double);
void set_maximum_frames_per_second(double);
enum class PaletteMode { enum class PaletteMode {
Default, Default,