From b8e377378b8dd2896e8662739c87df2389e16d82 Mon Sep 17 00:00:00 2001 From: Ruslan Kabatsayev Date: Sat, 25 Jan 2025 22:35:58 +0800 Subject: [PATCH] Fixing fractional OS scaling support in Wayland Generally, the problem stems from the fact that Wayland reports its scaling factor as an integer, which then Qt just takes for granted until it somehow manages to notice, when initializing a(n OpenGL-enabled) widget, that the factor is actually not integral, and then we can query it from the widget. QScreen still remains with this old wrong factor, so this factor shouldn't be queried from it. Fixes #4089. --- src/StelMainView.cpp | 20 ++++++++------------ src/core/StelApp.cpp | 6 +++--- src/gui/StelGuiItems.cpp | 2 +- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/StelMainView.cpp b/src/StelMainView.cpp index 74da53fc0bc92..a33c2e4f6e1e9 100644 --- a/src/StelMainView.cpp +++ b/src/StelMainView.cpp @@ -395,17 +395,14 @@ class StelRootItem : public QGraphicsObject //a sanity check Q_ASSERT(mainView->glContext() == QOpenGLContext::currentContext()); - { - static int oldViewportWidth, oldViewportHeight; - GLint viewport[4] = {}; - GL(QOpenGLContext::currentContext()->functions()->glGetIntegerv(GL_VIEWPORT, viewport)); - if(viewport[2] != oldViewportWidth || viewport[3] != oldViewportHeight) - { - qDebug() << "Early painting: OpenGL viewport size: " << viewport[2] << "x" << viewport[3]; - oldViewportWidth = viewport[2]; - oldViewportHeight = viewport[3]; - } - } + StelApp& app = StelApp::getInstance(); + + // This can change even on the screen even without actual system settings change. + // E.g. in KWin 6.1.5 with Wayland backend, if we set 150% scale in System Settings, + // the app first gets device pixel ratio of 200%, then the widgets are rescaled to 150% + // while the screen still remains at 200%. This is ugly, and shouldn't behave like this, + // but the following call seems to be enough to get things working right. + app.setDevicePixelsPerPixel(mainView->devicePixelRatioF()); const double now = StelApp::getTotalRunTime(); double dt = now - previousPaintTime; @@ -421,7 +418,6 @@ class StelRootItem : public QGraphicsObject #endif //update and draw - StelApp& app = StelApp::getInstance(); app.update(dt); // may also issue GL calls app.draw(); painter->endNativePainting(); diff --git a/src/core/StelApp.cpp b/src/core/StelApp.cpp index ad574d19de34e..5b17edaa96d29 100644 --- a/src/core/StelApp.cpp +++ b/src/core/StelApp.cpp @@ -444,9 +444,8 @@ void StelApp::init(QSettings* conf) gl = QOpenGLContext::currentContext()->functions(); confSettings = conf; - devicePixelsPerPixel = QOpenGLContext::currentContext()->screen()->devicePixelRatio(); - if (devicePixelsPerPixel>1) - qDebug() << "Detected a high resolution device! Device pixel ratio:" << devicePixelsPerPixel; + devicePixelsPerPixel = StelMainView::getInstance().devicePixelRatioF(); + qDebug() << "Initial high-DPI scaling factor:" << devicePixelsPerPixel; setScreenFontSize(confSettings->value("gui/screen_font_size", getDefaultGuiFontSize()).toInt()); setGuiFontSize(confSettings->value("gui/gui_font_size", getDefaultGuiFontSize()).toInt()); @@ -1387,6 +1386,7 @@ void StelApp::setDevicePixelsPerPixel(qreal dppp) // Check that the device-independent pixel size didn't change if (!viewportEffect && !fuzzyEquals(devicePixelsPerPixel, dppp)) { + qDebug() << "Changing high-DPI scaling factor from" << devicePixelsPerPixel << "to" << dppp; devicePixelsPerPixel = dppp; StelProjector::StelProjectorParams params = core->getCurrentStelProjectorParams(); params.devicePixelsPerPixel = devicePixelsPerPixel; diff --git a/src/gui/StelGuiItems.cpp b/src/gui/StelGuiItems.cpp index 28b794274eb88..9c7f1de361528 100644 --- a/src/gui/StelGuiItems.cpp +++ b/src/gui/StelGuiItems.cpp @@ -386,7 +386,7 @@ void StelButton::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidg * rectangles. * Our keeping QPixmap alive instead of deleting it on return from this function prevents this. */ - const double ratio = QOpenGLContext::currentContext()->screen()->devicePixelRatio(); + const double ratio = StelApp::getInstance().getDevicePixelsPerPixel(); if(scaledCurrentPixmap.isNull() || ratio != scaledCurrentPixmap.devicePixelRatioF()) { const auto size = boundingRect().size() * ratio;