FedoraQt / QGnomePlatform

QPlatformTheme for a better Qt application inclusion in GNOME
GNU Lesser General Public License v2.1
263 stars 38 forks source link

Some font scaling factors (like 1.4) are ignored #44

Open ilmaisin opened 5 years ago

ilmaisin commented 5 years ago

I reported a bug against KDE's flatpak runtime. I run Gnome as my DE and if I set my font scaling factor to 1.4 via the tweak-tool, it does not apply to Qt flatpak apps. KDE's Jan Grulich traced the problem to QGnomePlatform.

https://bugs.kde.org/show_bug.cgi?id=407194

It looks it depends on the value you set to font-scaling, if I use 1.4, then it doesn't work, but if I use 1.5 then it scales. There is some logic apparently in Qt doing this work based on DPI. We used to do scaling in QGnomePlatform, but it was removed because of this Qt behavior. It looks it wasn't a good decision to drop it completely and we will need to just implement it properly.

See: https://github.com/FedoraQt/QGnomePlatform/commit/687c74e175d1acc84de075f8f13180d78ef8391e

Please open a bug for QGnomePlatform as this has nothing to do with KDE.

According to Grulich, it is not a flatpak specific bug. For me, non-flatpak Qt apps work fine, though, but it is probably because 687c74e175d is not yet in CentOS. He also noticed that scaling factor 1.5 works fine, and I can confirm that.

This is important for users with visual impairment as well as those who use a high DPI display.

ilya-fedin commented 2 years ago

There are two problems.

  1. Qt scales interface with scaling factor * text scaling factor on X11. I've raised that at https://bugreports.qt.io/browse/QTBUG-84082?focusedCommentId=587793&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-587793, but got no response unfortunately. The fix as simple as follows, but needs to be applied by Qt's xcb platform code:

    diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
    index bb33f393ec..5ecf730f6c 100644
    --- a/src/plugins/platforms/xcb/qxcbscreen.cpp
    +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
    @@ -77,15 +77,19 @@ QXcbVirtualDesktop::QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t
             xcb_depth_next(&depth_iterator);
         }
    
    -    auto dpiChangedCallback = [](QXcbVirtualDesktop *desktop, const QByteArray &, const QVariant &property, void *) {
    -        if (!desktop->setDpiFromXSettings(property))
    +    auto dpiChangedCallback = [](QXcbVirtualDesktop *desktop, const QByteArray &name, const QVariant &property, void *) {
    +        const auto dpi = desktop->dpiFromXSettings(property);
    +        auto &oldDpi = name == "Gdk/UnscaledDPI"_L1 ? desktop->m_forcedBaseDpi : desktop->m_forcedDpi;
    +        if (dpi <= 0 || oldDpi == dpi)
                 return;
    -        const auto dpi = desktop->forcedDpi();
    +        oldDpi = dpi;
             for (QXcbScreen *screen : desktop->connection()->screens())
    -            QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen->QPlatformScreen::screen(), dpi, dpi);
    +            QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen->QPlatformScreen::screen(), desktop->m_forcedDpi, desktop->m_forcedDpi);
         };
    -    setDpiFromXSettings(xSettings()->setting("Xft/DPI"));
    +    m_forcedDpi = dpiFromXSettings(xSettings()->setting("Xft/DPI"));
    +    m_forcedBaseDpi = dpiFromXSettings(xSettings()->setting("Gdk/UnscaledDPI"));
         xSettings()->registerCallbackForProperty("Xft/DPI", dpiChangedCallback, nullptr);
    +    xSettings()->registerCallbackForProperty("Gdk/UnscaledDPI", dpiChangedCallback, nullptr);
     }
    
     QXcbVirtualDesktop::~QXcbVirtualDesktop()
    @@ -385,17 +389,13 @@ void QXcbVirtualDesktop::readXResources()
         }
     }
    
    -bool QXcbVirtualDesktop::setDpiFromXSettings(const QVariant &property)
    +int QXcbVirtualDesktop::dpiFromXSettings(const QVariant &property)
     {
         bool ok;
         int dpiTimes1k = property.toInt(&ok);
         if (!ok)
    -        return false;
    -    int dpi = dpiTimes1k / 1024;
    -    if (m_forcedDpi == dpi)
    -        return false;
    -    m_forcedDpi = dpi;
    -    return true;
    +        return -1;
    +    return dpiTimes1k / 1024;
     }
    
     QSurfaceFormat QXcbVirtualDesktop::surfaceFormatFor(const QSurfaceFormat &format) const
    @@ -867,6 +867,15 @@ QDpi QXcbScreen::logicalDpi() const
         return QDpi(96, 96);
     }
    
    +QDpi QXcbScreen::logicalBaseDpi() const
    +{
    +    const int dpi = forcedBaseDpi();
    +    if (dpi > 0)
    +        return QDpi(dpi, dpi);
    +
    +    return QDpi(96, 96);
    +}
    +
     QPlatformCursor *QXcbScreen::cursor() const
     {
         return m_cursor;
    diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
    index 12c13ef80e..ba6147c858 100644
    --- a/src/plugins/platforms/xcb/qxcbscreen.h
    +++ b/src/plugins/platforms/xcb/qxcbscreen.h
    @@ -60,6 +60,7 @@ public:
         void handleScreenChange(xcb_randr_screen_change_notify_event_t *change_event);
    
         int forcedDpi() const { return m_forcedDpi; }
    +    int forcedBaseDpi() const { return m_forcedBaseDpi; }
         QFontEngine::HintStyle hintStyle() const { return m_hintStyle; }
         QFontEngine::SubpixelAntialiasingType subpixelType() const { return m_subpixelType; }
         int antialiasingEnabled() const { return m_antialiasingEnabled; }
    @@ -81,7 +82,7 @@ private:
                               QByteArray &stringValue);
         void readXResources();
    
    -    bool setDpiFromXSettings(const QVariant &property);
    +    int dpiFromXSettings(const QVariant &property);
    
         xcb_screen_t *m_screen;
         const int m_number;
    @@ -94,6 +95,7 @@ private:
         QRect m_workArea;
    
         int m_forcedDpi = -1;
    +    int m_forcedBaseDpi = -1;
         QFontEngine::HintStyle m_hintStyle = QFontEngine::HintStyle(-1);
         QFontEngine::SubpixelAntialiasingType m_subpixelType = QFontEngine::SubpixelAntialiasingType(-1);
         int m_antialiasingEnabled = -1;
    @@ -134,7 +136,7 @@ public:
         QColorSpace colorSpace() const override { return m_colorSpace; }
         QSizeF physicalSize() const override { return m_sizeMillimeters; }
         QDpi logicalDpi() const override;
    -    QDpi logicalBaseDpi() const override { return QDpi(96, 96); }
    +    QDpi logicalBaseDpi() const override;
         QPlatformCursor *cursor() const override;
         qreal refreshRate() const override { return m_refreshRate; }
         Qt::ScreenOrientation orientation() const override { return m_orientation; }

    I'm not sure whethe it's something acceptable though as it reads a gtk-specific setting.

  2. There's no such problem on Wayland, so the previous logic could be applied on wayland, but using manual point-to-pixel conversion: std::round(std::floor(fontSize * 96. / 72. * 100. + 0.5) / 100.). pango_font_description_get_size_is_absolute should say whether such conversion is needed. The result could be multiplied by text scaling factor and applied to QFont::setPixelSize.