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
m_device_pixel_ratio = devicePixelRatio();
m_current_screen = screen();
m_refresh_rate = m_current_screen->refreshRate();
if (QT_VERSION < QT_VERSION_CHECK(6, 6, 0) || QGuiApplication::platformName() != "wayland") {
setAttribute(Qt::WA_NativeWindow);
setAttribute(Qt::WA_DontCreateNativeAncestors);
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) {
if (m_device_pixel_ratio != 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::refreshRateChanged, nullptr, nullptr);
m_current_screen = screen;
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)
{
// 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; }
double refresh_rate() const { return m_refresh_rate; }
public slots:
void device_pixel_ratio_changed(qreal dpi);
void refresh_rate_changed(qreal refresh_rate);
void tab_title_changed(int index, QString const&);
void tab_favicon_changed(int index, QIcon const& icon);
void tab_audio_play_state_changed(int index, Web::HTML::AudioPlayState);
@ -174,6 +177,7 @@ private:
QScreen* m_current_screen;
double m_device_pixel_ratio { 0 };
double m_refresh_rate { 60.0 };
Web::CSS::PreferredColorScheme m_preferred_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->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->setVisible(false);
m_toolbar = new QToolBar(this);

View file

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

View file

@ -43,12 +43,16 @@ namespace Ladybird {
class Tab;
struct WebContentViewInitialState {
double maximum_frames_per_second { 60.0 };
};
class WebContentView final
: public QWidget
, public WebView::ViewImplementation {
Q_OBJECT
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;
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_device_pixel_ratio(double);
void set_maximum_frames_per_second(double);
enum class PaletteMode {
Default,