Skip to content

Commit

Permalink
Fixing fractional OS scaling support in Wayland
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
10110111 committed Jan 29, 2025
1 parent 282fa11 commit b8e3773
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 16 deletions.
20 changes: 8 additions & 12 deletions src/StelMainView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
Expand Down
6 changes: 3 additions & 3 deletions src/core/StelApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/gui/StelGuiItems.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit b8e3773

Please sign in to comment.