Compare commits
No commits in common. 'c9' and 'i10fe' have entirely different histories.
@ -1,2 +1,2 @@
|
||||
SOURCES/kde-5.15-rollup-20230411.patch.gz
|
||||
SOURCES/qtbase-everywhere-opensource-src-5.15.9.tar.xz
|
||||
SOURCES/qtbase-everywhere-opensource-src-5.15.15.tar.xz
|
||||
SOURCES/kde-5.15-rollup-20240904.patch.gz
|
||||
|
@ -1,2 +1,2 @@
|
||||
677b605bf6033bdfa84a676096ec6e77da6e844d SOURCES/kde-5.15-rollup-20230411.patch.gz
|
||||
a5bbeafa6319cd3e666b12ccc722a357de7230be SOURCES/qtbase-everywhere-opensource-src-5.15.9.tar.xz
|
||||
7120c075b63c4943225b8395a90575cf6b34e871 SOURCES/qtbase-everywhere-opensource-src-5.15.15.tar.xz
|
||||
497e1e84d1719d64974df5c882eb7a1a9773a4f3 SOURCES/kde-5.15-rollup-20240904.patch.gz
|
||||
|
@ -1,38 +0,0 @@
|
||||
From ea63c28efc1d2ecb467b83a34923d12462efa96f Mon Sep 17 00:00:00 2001
|
||||
From: Marc Mutz <marc.mutz@qt.io>
|
||||
Date: Tue, 12 Dec 2023 20:51:56 +0100
|
||||
Subject: [PATCH] HPack: fix a Yoda Condition
|
||||
|
||||
Putting the variable on the LHS of a relational operation makes the
|
||||
expression easier to read. In this case, we find that the whole
|
||||
expression is nonsensical as an overflow protection, because if
|
||||
name.size() + value.size() overflows, the result will exactly _not_
|
||||
be > max() - 32, because UB will have happened.
|
||||
|
||||
To be fixed in a follow-up commit.
|
||||
|
||||
As a drive-by, add parentheses around the RHS.
|
||||
|
||||
Change-Id: I35ce598884c37c51b74756b3bd2734b9aad63c09
|
||||
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
|
||||
(cherry picked from commit 658607a34ead214fbacbc2cca44915655c318ea9)
|
||||
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
|
||||
(cherry picked from commit 4f7efd41740107f90960116700e3134f5e433867)
|
||||
(cherry picked from commit 13c16b756900fe524f6d9534e8a07aa003c05e0c)
|
||||
(cherry picked from commit 1d4788a39668fb2dc5912a8d9c4272dc40e99f92)
|
||||
(cherry picked from commit 87de75b5cc946d196decaa6aef4792a6cac0b6db)
|
||||
---
|
||||
|
||||
diff --git a/src/network/access/http2/hpacktable.cpp b/src/network/access/http2/hpacktable.cpp
|
||||
index 834214f..ab166a6 100644
|
||||
--- a/src/network/access/http2/hpacktable.cpp
|
||||
+++ b/src/network/access/http2/hpacktable.cpp
|
||||
@@ -63,7 +63,7 @@
|
||||
// 32 octets of overhead."
|
||||
|
||||
const unsigned sum = unsigned(name.size() + value.size());
|
||||
- if (std::numeric_limits<unsigned>::max() - 32 < sum)
|
||||
+ if (sum > (std::numeric_limits<unsigned>::max() - 32))
|
||||
return HeaderSize();
|
||||
return HeaderSize(true, quint32(sum + 32));
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
From c41101241ce626dd38ee71d5a37c6aeb434eddf4 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Wed, 26 Jul 2023 12:06:29 +0200
|
||||
Subject: [PATCH 02/15] Add enum class Qt::Appearance
|
||||
|
||||
It has been decided to add an appearance property in QStyleHints, which
|
||||
will be propagated to classes that do not include QPlatformTheme.
|
||||
|
||||
Therefore an appearance enum class is added to the Qt namespace, thus
|
||||
being available to all Qt classes.
|
||||
---
|
||||
src/corelib/global/qnamespace.h | 7 +++++++
|
||||
src/corelib/global/qnamespace.qdoc | 11 +++++++++++
|
||||
2 files changed, 18 insertions(+)
|
||||
|
||||
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
|
||||
index bf19b1627b..acf2c26368 100644
|
||||
--- a/src/corelib/global/qnamespace.h
|
||||
+++ b/src/corelib/global/qnamespace.h
|
||||
@@ -123,6 +123,12 @@ public:
|
||||
UNICODE_ACCEL = 0x00000000
|
||||
};
|
||||
|
||||
+ enum class Appearance {
|
||||
+ Unknown = 0x0000,
|
||||
+ Light = 0x0001,
|
||||
+ Dark = 0x0002
|
||||
+ };
|
||||
+
|
||||
enum MouseButton {
|
||||
NoButton = 0x00000000,
|
||||
LeftButton = 0x00000001,
|
||||
@@ -1820,6 +1826,7 @@ public:
|
||||
QT_Q_ENUM(DayOfWeek)
|
||||
QT_Q_ENUM(CursorShape)
|
||||
QT_Q_ENUM(GlobalColor)
|
||||
+ QT_Q_ENUM(Appearance)
|
||||
QT_Q_ENUM(AspectRatioMode)
|
||||
QT_Q_ENUM(TransformationMode)
|
||||
QT_Q_FLAG(ImageConversionFlags)
|
||||
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
|
||||
index dbb9469bba..70cf8290f5 100644
|
||||
--- a/src/corelib/global/qnamespace.qdoc
|
||||
+++ b/src/corelib/global/qnamespace.qdoc
|
||||
@@ -841,6 +841,17 @@
|
||||
\sa QDockWidget::setAllowedAreas, QDockWidget::isAreaAllowed
|
||||
*/
|
||||
|
||||
+/*!
|
||||
+ \enum Qt::Appearance
|
||||
+
|
||||
+ Represents the appearance of an application's theme,
|
||||
+ defined by QGuiApplication::palette().
|
||||
+
|
||||
+ \value Unknown The appearance is unknown.
|
||||
+ \value Light The background colors are lighter than the text color, i.e. the theme is light.
|
||||
+ \value Dark The background colors are darker than the text color, i.e. the theme is dark.
|
||||
+*/
|
||||
+
|
||||
/*!
|
||||
\enum Qt::ImageConversionFlag
|
||||
|
||||
--
|
||||
2.41.0
|
||||
|
@ -1,59 +0,0 @@
|
||||
From 23c3fc483e8b6e21012a61f0bea884446f727776 Mon Sep 17 00:00:00 2001
|
||||
From: Marc Mutz <marc.mutz@qt.io>
|
||||
Date: Tue, 12 Dec 2023 22:08:07 +0100
|
||||
Subject: [PATCH] HPack: fix incorrect integer overflow check
|
||||
|
||||
This code never worked:
|
||||
|
||||
For the comparison with max() - 32 to trigger, on 32-bit platforms (or
|
||||
Qt 5) signed interger overflow would have had to happen in the
|
||||
addition of the two sizes. The compiler can therefore remove the
|
||||
overflow check as dead code.
|
||||
|
||||
On Qt 6 and 64-bit platforms, the signed integer addition would be
|
||||
very unlikely to overflow, but the following truncation to uint32
|
||||
would yield the correct result only in a narrow 32-value window just
|
||||
below UINT_MAX, if even that.
|
||||
|
||||
Fix by using the proper tool, qAddOverflow.
|
||||
|
||||
Manual conflict resolutions:
|
||||
- qAddOverflow doesn't exist in Qt 5, use private add_overflow
|
||||
predecessor API instead
|
||||
|
||||
Change-Id: I7599f2e75ff7f488077b0c60b81022591005661c
|
||||
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
|
||||
(cherry picked from commit ee5da1f2eaf8932aeca02ffea6e4c618585e29e3)
|
||||
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
|
||||
(cherry picked from commit debeb8878da2dc706ead04b6072ecbe7e5313860)
|
||||
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
||||
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
|
||||
(cherry picked from commit 811b9eef6d08d929af8708adbf2a5effb0eb62d7)
|
||||
(cherry picked from commit f931facd077ce945f1e42eaa3bead208822d3e00)
|
||||
(cherry picked from commit 9ef4ca5ecfed771dab890856130e93ef5ceabef5)
|
||||
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
|
||||
---
|
||||
|
||||
diff --git a/src/network/access/http2/hpacktable.cpp b/src/network/access/http2/hpacktable.cpp
|
||||
index ab166a6..de91fc0 100644
|
||||
--- a/src/network/access/http2/hpacktable.cpp
|
||||
+++ b/src/network/access/http2/hpacktable.cpp
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "hpacktable_p.h"
|
||||
|
||||
#include <QtCore/qdebug.h>
|
||||
+#include <QtCore/private/qnumeric_p.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
@@ -62,7 +63,9 @@
|
||||
// for counting the number of references to the name and value would have
|
||||
// 32 octets of overhead."
|
||||
|
||||
- const unsigned sum = unsigned(name.size() + value.size());
|
||||
+ size_t sum;
|
||||
+ if (add_overflow(size_t(name.size()), size_t(value.size()), &sum))
|
||||
+ return HeaderSize();
|
||||
if (sum > (std::numeric_limits<unsigned>::max() - 32))
|
||||
return HeaderSize();
|
||||
return HeaderSize(true, quint32(sum + 32));
|
@ -0,0 +1,78 @@
|
||||
From fb0bc2e9f466c37f398af4a7a374fee2b29f5073 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Wed, 26 Jul 2023 13:43:29 +0200
|
||||
Subject: [PATCH 03/15] Sync and assert StandardPixmap enums in QPlatformTheme
|
||||
and QStyle
|
||||
|
||||
Add missing enum values in QPlatformTheme::standardPixmap to sync with
|
||||
QStyle::standardPixmap changes from:
|
||||
785d2b9d0728bbbc0d2a92b7d4186a3114d54128
|
||||
aa5a595a98f1af4a514485268a18e6cb9cfec783
|
||||
|
||||
Add enum values NStandardPixmap at the bottom of both enums as well
|
||||
as an assertion in QStyle constructor that these values are identical.
|
||||
Add omitvalue for NStandardPixmap in QStyle (QPlatformTheme enum is
|
||||
not documented).
|
||||
---
|
||||
src/gui/kernel/qplatformtheme.h | 9 +++++++++
|
||||
src/widgets/styles/qstyle.cpp | 4 ++++
|
||||
src/widgets/styles/qstyle.h | 1 +
|
||||
3 files changed, 14 insertions(+)
|
||||
|
||||
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
|
||||
index 7e6c9d5740..99a30337f5 100644
|
||||
--- a/src/gui/kernel/qplatformtheme.h
|
||||
+++ b/src/gui/kernel/qplatformtheme.h
|
||||
@@ -256,6 +256,15 @@ public:
|
||||
MediaVolume,
|
||||
MediaVolumeMuted,
|
||||
LineEditClearButton,
|
||||
+ DialogYesToAllButton,
|
||||
+ DialogNoToAllButton,
|
||||
+ DialogSaveAllButton,
|
||||
+ DialogAbortButton,
|
||||
+ DialogRetryButton,
|
||||
+ DialogIgnoreButton,
|
||||
+ RestoreDefaultsButton,
|
||||
+ NStandardPixmap, // assertion value for sync with QStyle::StandardPixmap
|
||||
+
|
||||
// do not add any values below/greater than this
|
||||
CustomBase = 0xf0000000
|
||||
};
|
||||
diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp
|
||||
index 669f158b7b..18d21a843d 100644
|
||||
--- a/src/widgets/styles/qstyle.cpp
|
||||
+++ b/src/widgets/styles/qstyle.cpp
|
||||
@@ -412,6 +412,9 @@ QStyle::QStyle(QStylePrivate &dd)
|
||||
{
|
||||
Q_D(QStyle);
|
||||
d->proxyStyle = this;
|
||||
+ Q_STATIC_ASSERT_X(int(StandardPixmap::NStandardPixmap) ==
|
||||
+ int(QPlatformTheme::StandardPixmap::NStandardPixmap),
|
||||
+ "StandardPixmap in QPlatformTheme and QStyle out of sync");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -2117,6 +2120,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
|
||||
This enum value was added in Qt 5.14.
|
||||
\value SP_RestoreDefaultsButton Icon for a standard RestoreDefaults button in a QDialogButtonBox.
|
||||
This enum value was added in Qt 5.14.
|
||||
+ \omitvalue NStandardPixmap
|
||||
\value SP_CustomBase Base value for custom standard pixmaps;
|
||||
custom values must be greater than this value.
|
||||
|
||||
diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h
|
||||
index 5be1b4b290..9d98f76152 100644
|
||||
--- a/src/widgets/styles/qstyle.h
|
||||
+++ b/src/widgets/styles/qstyle.h
|
||||
@@ -845,6 +845,7 @@ public:
|
||||
SP_DialogRetryButton,
|
||||
SP_DialogIgnoreButton,
|
||||
SP_RestoreDefaultsButton,
|
||||
+ NStandardPixmap, // assertion value for sync with QPlatformTheme::StandardPixmap
|
||||
// do not add any values below/greater than this
|
||||
SP_CustomBase = 0xf0000000
|
||||
};
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,47 @@
|
||||
From 24b6ad903ab2ed620f8c754aafb727e6aa342aca Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Wed, 26 Jul 2023 15:38:13 +0200
|
||||
Subject: [PATCH 04/15] QGtk3Theme: subscribe to theme hint changes
|
||||
|
||||
---
|
||||
.../platformthemes/gtk3/qgtk3theme.cpp | 20 +++++++++++++++++++
|
||||
1 file changed, 20 insertions(+)
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
|
||||
index 42cb0c7d..248ed9d8 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "qgtk3theme.h"
|
||||
#include "qgtk3dialoghelpers.h"
|
||||
#include "qgtk3menu.h"
|
||||
+#include "qpa/qwindowsysteminterface.h"
|
||||
#include <QVariant>
|
||||
#include <QGuiApplication>
|
||||
|
||||
@@ -110,6 +111,25 @@ QGtk3Theme::QGtk3Theme()
|
||||
/* Use our custom log handler. */
|
||||
g_log_set_handler("Gtk", G_LOG_LEVEL_MESSAGE, gtkMessageHandler, nullptr);
|
||||
|
||||
+#define SETTING_CONNECT(setting) g_signal_connect(settings, "notify::" setting, G_CALLBACK(notifyThemeChanged), nullptr)
|
||||
+ auto notifyThemeChanged = [] {
|
||||
+ QWindowSystemInterface::handleThemeChange(nullptr);
|
||||
+ };
|
||||
+
|
||||
+ GtkSettings *settings = gtk_settings_get_default();
|
||||
+ SETTING_CONNECT("gtk-cursor-blink-time");
|
||||
+ SETTING_CONNECT("gtk-double-click-distance");
|
||||
+ SETTING_CONNECT("gtk-double-click-time");
|
||||
+ SETTING_CONNECT("gtk-long-press-time");
|
||||
+ SETTING_CONNECT("gtk-entry-password-hint-timeout");
|
||||
+ SETTING_CONNECT("gtk-dnd-drag-threshold");
|
||||
+ SETTING_CONNECT("gtk-icon-theme-name");
|
||||
+ SETTING_CONNECT("gtk-fallback-icon-theme");
|
||||
+ SETTING_CONNECT("gtk-font-name");
|
||||
+ SETTING_CONNECT("gtk-application-prefer-dark-theme");
|
||||
+ SETTING_CONNECT("gtk-theme-name");
|
||||
+#undef SETTING_CONNECT
|
||||
+
|
||||
/* Set XCURSOR_SIZE and XCURSOR_THEME for Wayland sessions */
|
||||
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"))) {
|
||||
if (qEnvironmentVariableIsEmpty("XCURSOR_SIZE")) {
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,48 @@
|
||||
From 99fd51406053e789b9e02dd5fdbf63d79cb4d7ff Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Thu, 27 Jul 2023 12:36:14 +0200
|
||||
Subject: [PATCH 08/15] Fix checkbox and radiobutton background in QGtk3Theme
|
||||
|
||||
The background color for radio buttons and checkboxes was not
|
||||
correctly read from the current GTK3 theme in light mode.
|
||||
This has lead to identical colors for indicators and background of
|
||||
radio buttons and checkboxes for certain GTK themes (e.g. Breeze).
|
||||
|
||||
This patch sets the GTK default foreground color to the base color of
|
||||
palettes for checkboxes and radio buttons.
|
||||
---
|
||||
src/plugins/platformthemes/gtk3/qgtk3storage.cpp | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
index 0a1fa6ef97..d5d0e2c8e6 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
@@ -377,7 +377,6 @@ void QGtk3Storage::createMapping()
|
||||
ADD(Normal, Button);
|
||||
ADD(Normal, Base);
|
||||
ADD(Inactive, Base);
|
||||
- ADD(Normal, Window); // redundant
|
||||
ADD(Inactive, Window);
|
||||
LIGHTER(Normal, Window, 125);
|
||||
ADD(Normal, Light);
|
||||
@@ -391,7 +390,6 @@ void QGtk3Storage::createMapping()
|
||||
LIGHTER(Normal, WindowText, 50);
|
||||
ADD(Disabled, Text);
|
||||
ADD(Disabled, WindowText);
|
||||
- //ADD(Normal, ButtonText);
|
||||
ADD(Inactive, ButtonText);
|
||||
GTK(button, Text, NORMAL);
|
||||
ADD(Disabled, ButtonText);
|
||||
@@ -427,6 +425,8 @@ void QGtk3Storage::createMapping()
|
||||
// Checkbox and Radio Button
|
||||
GTK(button, Text, ACTIVE);
|
||||
ADD(Normal, Base, Dark);
|
||||
+ GTK(Default, Background, NORMAL);
|
||||
+ ADD(All, Base);
|
||||
GTK(button, Text, NORMAL);
|
||||
ADD(Normal, Base, Light);
|
||||
SAVE(CheckBoxPalette);
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,51 @@
|
||||
From 41d23f13c9aede66a6c9044869b0ef5f52f7d71d Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Thu, 27 Jul 2023 12:38:53 +0200
|
||||
Subject: [PATCH 09/15] Cleanup QGtk3Theme
|
||||
|
||||
1. Remove unused include.
|
||||
2. Replace unnecessary null checks with asserts.
|
||||
3. Remove dead code after the cleanup.
|
||||
---
|
||||
src/plugins/platformthemes/gtk3/qgtk3theme.cpp | 12 ++++++++----
|
||||
1 file changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
|
||||
index 5f5fee4f3b..0de9dd3866 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
|
||||
@@ -239,23 +239,27 @@ bool QGtk3Theme::useNativeFileDialog()
|
||||
|
||||
const QPalette *QGtk3Theme::palette(Palette type) const
|
||||
{
|
||||
- return m_storage ? m_storage->palette(type) : QPlatformTheme::palette(type);
|
||||
+ Q_ASSERT(m_storage);
|
||||
+ return m_storage->palette(type);
|
||||
}
|
||||
|
||||
QPixmap QGtk3Theme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
|
||||
{
|
||||
- return m_storage ? m_storage->standardPixmap(sp, size) : QPlatformTheme::standardPixmap(sp, size);
|
||||
+ Q_ASSERT(m_storage);
|
||||
+ return m_storage->standardPixmap(sp, size);
|
||||
}
|
||||
|
||||
const QFont *QGtk3Theme::font(Font type) const
|
||||
{
|
||||
- return m_storage ? m_storage->font(type) : QGnomeTheme::font(type);
|
||||
+ Q_ASSERT(m_storage);
|
||||
+ return m_storage->font(type);
|
||||
}
|
||||
|
||||
QIcon QGtk3Theme::fileIcon(const QFileInfo &fileInfo,
|
||||
QPlatformTheme::IconOptions iconOptions) const
|
||||
{
|
||||
- return m_storage ? m_storage->fileIcon(fileInfo) : QGnomeTheme::fileIcon(fileInfo, iconOptions);
|
||||
+ Q_ASSERT(m_storage);
|
||||
+ return m_storage->fileIcon(fileInfo);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,85 @@
|
||||
From f0117fa2110e8b6d71c82272fda1d264e7921a24 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Thu, 27 Jul 2023 12:40:32 +0200
|
||||
Subject: [PATCH 10/15] Detect appearance by colors unless GTK theme name
|
||||
contains "dark"
|
||||
|
||||
QGtk3Theme detects the appearance property by theme name: If the name
|
||||
contains the keyword "dark", the theme is considered to be dark and
|
||||
otherwise light.
|
||||
|
||||
This detection logic fails, when the GTK theme is dark without
|
||||
containing the "dark" keyword, e.g. the dark theme "Adapta-Nokto".
|
||||
While QGtk3Theme imports the right colors in that case, it wrongly
|
||||
identifies a light theme.
|
||||
|
||||
This patch adapts the detection logic: If the theme name contains the
|
||||
"dark" keyword, it is considered a dark theme without further checks.
|
||||
If it doesn't, the current GTK3 theme's default background and
|
||||
foreground colors will be read. If the foreground is lighter than the
|
||||
background, the theme is considered dark. If the background is lighter
|
||||
than the foreground, the theme is considered light. If both colors are
|
||||
identical, the appearance will be Qt::Appearance::Unknown.
|
||||
---
|
||||
.../platformthemes/gtk3/qgtk3interface.cpp | 16 ++++++++++++++++
|
||||
.../platformthemes/gtk3/qgtk3interface_p.h | 3 +++
|
||||
src/plugins/platformthemes/gtk3/qgtk3storage.cpp | 2 +-
|
||||
3 files changed, 20 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3interface.cpp b/src/plugins/platformthemes/gtk3/qgtk3interface.cpp
|
||||
index d932b250a5..e2444197da 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3interface.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3interface.cpp
|
||||
@@ -400,6 +400,22 @@ const QString QGtk3Interface::themeName() const
|
||||
return QLatin1String(theme_name);
|
||||
}
|
||||
|
||||
+Qt::Appearance QGtk3Interface::appearanceByColors() const
|
||||
+{
|
||||
+ const QColor background = color(widget(QGtkWidget::gtk_Default),
|
||||
+ QGtkColorSource::Background,
|
||||
+ GTK_STATE_FLAG_ACTIVE);
|
||||
+ const QColor foreground = color(widget(QGtkWidget::gtk_Default),
|
||||
+ QGtkColorSource::Foreground,
|
||||
+ GTK_STATE_FLAG_ACTIVE);
|
||||
+
|
||||
+ if (foreground.lightness() > background.lightness())
|
||||
+ return Qt::Appearance::Dark;
|
||||
+ if (foreground.lightness() < background.lightness())
|
||||
+ return Qt::Appearance::Light;
|
||||
+ return Qt::Appearance::Unknown;
|
||||
+}
|
||||
+
|
||||
inline constexpr QGtk3Interface::QGtkWidget QGtk3Interface::toWidgetType(QPlatformTheme::Font type)
|
||||
{
|
||||
switch (type) {
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3interface_p.h b/src/plugins/platformthemes/gtk3/qgtk3interface_p.h
|
||||
index 8997a64e76..e04025923d 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3interface_p.h
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3interface_p.h
|
||||
@@ -97,6 +97,9 @@ public:
|
||||
// Return current GTK theme name
|
||||
const QString themeName() const;
|
||||
|
||||
+ // Derive appearance from default colors
|
||||
+ Qt::Appearance appearanceByColors() const;
|
||||
+
|
||||
// Convert GTK state to/from string
|
||||
static int toGtkState(const QString &state);
|
||||
static const QLatin1String fromGtkState(GtkStateFlags state);
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
index d5d0e2c8e6..0b6b8e8523 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
@@ -222,7 +222,7 @@ void QGtk3Storage::populateMap()
|
||||
|
||||
// Derive appearance from theme name
|
||||
m_appearance = newThemeName.contains("dark", Qt::CaseInsensitive)
|
||||
- ? Qt::Appearance::Dark : Qt::Appearance::Light;
|
||||
+ ? Qt::Appearance::Dark : m_interface->appearanceByColors();
|
||||
|
||||
if (m_themeName.isEmpty()) {
|
||||
qCDebug(lcQGtk3Interface) << "GTK theme initialized:" << newThemeName << m_appearance;
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,120 @@
|
||||
From 85d72b8bf0db7349dafce252d18ce17677eef46e Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Thu, 27 Jul 2023 12:41:06 +0200
|
||||
Subject: [PATCH 11/15] Change parsing log output in QGtk3Json from qCDebug to
|
||||
qCInfo
|
||||
|
||||
When a palette mapping is imported from a Json file, parsing errors are
|
||||
logged with qCDebug. This prevents errors from being logged in release
|
||||
builds.
|
||||
|
||||
This patch replaces qCDebug with qCInfo for Json parsing to make errors
|
||||
visible when the logging category qt.qpa.gtk is activated.
|
||||
---
|
||||
src/plugins/platformthemes/gtk3/qgtk3json.cpp | 23 +++++++++----------
|
||||
1 file changed, 11 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3json.cpp b/src/plugins/platformthemes/gtk3/qgtk3json.cpp
|
||||
index f4d5b50ec5..9db1ea3d20 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3json.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3json.cpp
|
||||
@@ -331,7 +331,7 @@ bool QGtk3Json::load(QGtk3Storage::PaletteMap &map, const QJsonDocument &doc)
|
||||
{
|
||||
#define GETSTR(obj, key)\
|
||||
if (!obj.contains(key)) {\
|
||||
- qCDebug(lcQGtk3Interface) << key << "missing for palette" << paletteName\
|
||||
+ qCInfo(lcQGtk3Interface) << key << "missing for palette" << paletteName\
|
||||
<< ", Brush" << colorRoleName;\
|
||||
return false;\
|
||||
}\
|
||||
@@ -339,7 +339,7 @@ bool QGtk3Json::load(QGtk3Storage::PaletteMap &map, const QJsonDocument &doc)
|
||||
|
||||
#define GETINT(obj, key, var) GETSTR(obj, key);\
|
||||
if (!obj[key].isDouble()) {\
|
||||
- qCDebug(lcQGtk3Interface) << key << "type mismatch" << value\
|
||||
+ qCInfo(lcQGtk3Interface) << key << "type mismatch" << value\
|
||||
<< "is not an integer!"\
|
||||
<< "(Palette" << paletteName << "), Brush" << colorRoleName;\
|
||||
return false;\
|
||||
@@ -349,7 +349,7 @@ bool QGtk3Json::load(QGtk3Storage::PaletteMap &map, const QJsonDocument &doc)
|
||||
map.clear();
|
||||
const QJsonObject top(doc.object());
|
||||
if (doc.isEmpty() || top.isEmpty() || !top.contains(cePalettes)) {
|
||||
- qCDebug(lcQGtk3Interface) << "Document does not contain Palettes.";
|
||||
+ qCInfo(lcQGtk3Interface) << "Document does not contain Palettes.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -358,13 +358,12 @@ bool QGtk3Json::load(QGtk3Storage::PaletteMap &map, const QJsonDocument &doc)
|
||||
bool ok;
|
||||
const QPlatformTheme::Palette paletteType = toPalette(paletteName);
|
||||
if (paletteType == QPlatformTheme::NPalettes) {
|
||||
- qCDebug(lcQGtk3Interface) << "Invalid Palette name:" << paletteName;
|
||||
- return false;
|
||||
+ qCInfo(lcQGtk3Interface) << "Invalid Palette name:" << paletteName;
|
||||
}
|
||||
const QJsonObject &paletteObject = top[cePalettes][paletteName].toObject();
|
||||
const QStringList &brushList = paletteObject.keys();
|
||||
if (brushList.isEmpty()) {
|
||||
- qCDebug(lcQGtk3Interface) << "Palette" << paletteName << "does not contain brushes";
|
||||
+ qCInfo(lcQGtk3Interface) << "Palette" << paletteName << "does not contain brushes";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -374,7 +373,7 @@ bool QGtk3Json::load(QGtk3Storage::PaletteMap &map, const QJsonDocument &doc)
|
||||
const int intVal = QMetaEnum::fromType<QPalette::ColorRole>().keyToValue(colorRoleName
|
||||
.toLatin1().constData(), &ok);
|
||||
if (!ok) {
|
||||
- qCDebug(lcQGtk3Interface) << "Palette" << paletteName
|
||||
+ qCInfo(lcQGtk3Interface) << "Palette" << paletteName
|
||||
<< "contains invalid color role" << colorRoleName;
|
||||
return false;
|
||||
}
|
||||
@@ -383,7 +382,7 @@ bool QGtk3Json::load(QGtk3Storage::PaletteMap &map, const QJsonDocument &doc)
|
||||
for (int brushIndex = 0; brushIndex < brushArray.size(); ++brushIndex) {
|
||||
const QJsonObject brushObject = brushArray.at(brushIndex).toObject();
|
||||
if (brushObject.isEmpty()) {
|
||||
- qCDebug(lcQGtk3Interface) << "Brush specification missing at for palette"
|
||||
+ qCInfo(lcQGtk3Interface) << "Brush specification missing at for palette"
|
||||
<< paletteName << ", Brush" << colorRoleName;
|
||||
return false;
|
||||
}
|
||||
@@ -399,7 +398,7 @@ bool QGtk3Json::load(QGtk3Storage::PaletteMap &map, const QJsonDocument &doc)
|
||||
QGtk3Storage::Source s;
|
||||
|
||||
if (!brushObject.contains(ceData) || !brushObject[ceData].isObject()) {
|
||||
- qCDebug(lcQGtk3Interface) << "Source specification missing for palette" << paletteName
|
||||
+ qCInfo(lcQGtk3Interface) << "Source specification missing for palette" << paletteName
|
||||
<< "Brush" << colorRoleName;
|
||||
return false;
|
||||
}
|
||||
@@ -421,7 +420,7 @@ bool QGtk3Json::load(QGtk3Storage::PaletteMap &map, const QJsonDocument &doc)
|
||||
|
||||
case QGtk3Storage::SourceType::Fixed: {
|
||||
if (!sourceObject.contains(ceBrush)) {
|
||||
- qCDebug(lcQGtk3Interface) << "Fixed brush specification missing for palette" << paletteName
|
||||
+ qCInfo(lcQGtk3Interface) << "Fixed brush specification missing for palette" << paletteName
|
||||
<< "Brush" << colorRoleName;
|
||||
return false;
|
||||
}
|
||||
@@ -431,7 +430,7 @@ bool QGtk3Json::load(QGtk3Storage::PaletteMap &map, const QJsonDocument &doc)
|
||||
GETSTR(fixedSource, ceColor);
|
||||
const QColor color(value);
|
||||
if (!color.isValid()) {
|
||||
- qCDebug(lcQGtk3Interface) << "Color" << value << "can't be parsed for:" << paletteName
|
||||
+ qCInfo(lcQGtk3Interface) << "Color" << value << "can't be parsed for:" << paletteName
|
||||
<< "Brush" << colorRoleName;
|
||||
return false;
|
||||
}
|
||||
@@ -459,7 +458,7 @@ bool QGtk3Json::load(QGtk3Storage::PaletteMap &map, const QJsonDocument &doc)
|
||||
break;
|
||||
|
||||
case QGtk3Storage::SourceType::Invalid:
|
||||
- qCDebug(lcQGtk3Interface) << "Invalid source type for palette" << paletteName
|
||||
+ qInfo(lcQGtk3Interface) << "Invalid source type for palette" << paletteName
|
||||
<< "Brush." << colorRoleName;
|
||||
return false;
|
||||
}
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,400 @@
|
||||
From a2c6ba19ea2aafd1ec92fdd150ac14fe2424a394 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Thu, 27 Jul 2023 12:42:04 +0200
|
||||
Subject: [PATCH 12/15] Document QGtk3Interface
|
||||
|
||||
Add internal documentation to header and implementation of
|
||||
QGtk3Interface
|
||||
---
|
||||
.../platformthemes/gtk3/qgtk3interface.cpp | 161 ++++++++++++++++--
|
||||
.../platformthemes/gtk3/qgtk3interface_p.h | 43 ++++-
|
||||
2 files changed, 183 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3interface.cpp b/src/plugins/platformthemes/gtk3/qgtk3interface.cpp
|
||||
index e2444197da..0fab1220b4 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3interface.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3interface.cpp
|
||||
@@ -65,6 +65,14 @@ QGtk3Interface::~QGtk3Interface()
|
||||
gtk_widget_destroy(v.second);
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Converts a string into the GtkStateFlags enum.
|
||||
+
|
||||
+ Converts a string formatted GTK color \param state into an enum value.
|
||||
+ Returns an integer corresponding to GtkStateFlags.
|
||||
+ Returns -1 if \param state does not correspond to a valid enum key.
|
||||
+ */
|
||||
int QGtk3Interface::toGtkState(const QString &state)
|
||||
{
|
||||
#define CASE(x) \
|
||||
@@ -92,6 +100,10 @@ int QGtk3Interface::toGtkState(const QString &state)
|
||||
#undef CASE
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Returns \param state converted into a string.
|
||||
+ */
|
||||
const QLatin1String QGtk3Interface::fromGtkState(GtkStateFlags state)
|
||||
{
|
||||
#define CASE(x) case GTK_STATE_FLAG_ ##x: return QLatin1String(#x)
|
||||
@@ -103,9 +115,12 @@ const QLatin1String QGtk3Interface::fromGtkState(GtkStateFlags state)
|
||||
#undef CONVERT
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Populates the internal map used to find a GTK color's source and fallback generic color.
|
||||
+ */
|
||||
void QGtk3Interface::initColorMap()
|
||||
{
|
||||
- // Populate map with default values
|
||||
#define SAVE(src, state, prop, def)\
|
||||
{ColorKey({QGtkColorSource::src, GTK_STATE_FLAG_ ##state}), ColorValue({#prop, QGtkColorDefault::def})}
|
||||
|
||||
@@ -132,8 +147,17 @@ void QGtk3Interface::initColorMap()
|
||||
qCDebug(lcQGtk3Interface) << "Color map populated from defaults.";
|
||||
}
|
||||
|
||||
-// Return an image rather than an icon or a pixmap:
|
||||
-// Image can be cached and re-scaled to different sizes if requested multiple times
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Returns a QImage corresponding to \param standardPixmap.
|
||||
+
|
||||
+ A QImage (not a QPixmap) is returned so it can be cached and re-scaled in case the pixmap is
|
||||
+ requested multiple times with different resolutions.
|
||||
+
|
||||
+ \note Rather than defaulting to a QImage(), all QPlatformTheme::StandardPixmap enum values have
|
||||
+ been mentioned explicitly.
|
||||
+ That way they can be covered more easily in case additional icons are provided by GTK.
|
||||
+ */
|
||||
QImage QGtk3Interface::standardPixmap(QPlatformTheme::StandardPixmap standardPixmap) const
|
||||
{
|
||||
switch (standardPixmap) {
|
||||
@@ -235,6 +259,10 @@ QImage QGtk3Interface::standardPixmap(QPlatformTheme::StandardPixmap standardPix
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Returns a QImage for a given GTK \param iconName.
|
||||
+ */
|
||||
QImage QGtk3Interface::qt_gtk_get_icon(const char* iconName) const
|
||||
{
|
||||
GtkIconSet* iconSet = gtk_icon_factory_lookup_default (iconName);
|
||||
@@ -242,14 +270,23 @@ QImage QGtk3Interface::qt_gtk_get_icon(const char* iconName) const
|
||||
return qt_convert_gdk_pixbuf(icon);
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Returns a QImage converted from the GDK pixel buffer \param buf.
|
||||
+
|
||||
+ The ability to convert GdkPixbuf to QImage relies on the following assumptions:
|
||||
+ \list
|
||||
+ \li QImage uses uchar as a data container (unasserted)
|
||||
+ \li the types guint8 and uchar are identical (statically asserted)
|
||||
+ \li GDK pixel buffer uses 8 bits per sample (assumed at runtime)
|
||||
+ \li GDK pixel buffer has 4 channels (assumed at runtime)
|
||||
+ \endlist
|
||||
+ */
|
||||
QImage QGtk3Interface::qt_convert_gdk_pixbuf(GdkPixbuf *buf) const
|
||||
{
|
||||
if (!buf)
|
||||
return QImage();
|
||||
|
||||
- // Ability to convert GdkPixbuf to QImage relies on the assumptions, that
|
||||
- // - QImage uses uchar as a data container
|
||||
- // - the types guint8 and uchar are identical
|
||||
const guint8 *gdata = gdk_pixbuf_read_pixels(buf);
|
||||
static_assert(std::is_same<decltype(gdata), const uchar *>::value,
|
||||
"guint8 has diverted from uchar. Code needs fixing.");
|
||||
@@ -264,6 +301,13 @@ QImage QGtk3Interface::qt_convert_gdk_pixbuf(GdkPixbuf *buf) const
|
||||
return converted.copy(); // detatch to survive lifetime of buf
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Instantiate a new GTK widget.
|
||||
+
|
||||
+ Returns a pointer to a new GTK widget of \param type, allocated on the heap.
|
||||
+ Returns nullptr of gtk_Default has is passed.
|
||||
+ */
|
||||
GtkWidget *QGtk3Interface::qt_new_gtkWidget(QGtkWidget type) const
|
||||
{
|
||||
#define CASE(Type)\
|
||||
@@ -298,6 +342,14 @@ GtkWidget *QGtk3Interface::qt_new_gtkWidget(QGtkWidget type) const
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Read a GTK widget's color from a generic color getter.
|
||||
+
|
||||
+ This method returns a generic color of \param con, a given GTK style context.
|
||||
+ The requested color is defined by \param def and the GTK color-state \param state.
|
||||
+ The return type is GDK color in RGBA format.
|
||||
+ */
|
||||
GdkRGBA QGtk3Interface::genericColor(GtkStyleContext *con, GtkStateFlags state, QGtkColorDefault def) const
|
||||
{
|
||||
GdkRGBA color;
|
||||
@@ -316,9 +368,16 @@ GdkRGBA QGtk3Interface::genericColor(GtkStyleContext *con, GtkStateFlags state,
|
||||
#undef CASE
|
||||
}
|
||||
|
||||
-// Deliver a QColor from a GTK widget, a source type and a GTK widget state
|
||||
-// Fall back to the generic color getter of source/state if the property name does not exist
|
||||
-// Fall back to a hard coded generic color getter of source/state are not mapped
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Read a GTK widget's color from a property.
|
||||
+
|
||||
+ Returns a color of GTK-widget \param widget, defined by \param source and \param state.
|
||||
+ The return type is GDK color in RGBA format.
|
||||
+
|
||||
+ \note If no corresponding property can be found for \param source, the method falls back to a
|
||||
+ suitable generic color.
|
||||
+ */
|
||||
QColor QGtk3Interface::color(GtkWidget *widget, QGtkColorSource source, GtkStateFlags state) const
|
||||
{
|
||||
GdkRGBA col;
|
||||
@@ -355,7 +414,15 @@ QColor QGtk3Interface::color(GtkWidget *widget, QGtkColorSource source, GtkState
|
||||
#undef CASE
|
||||
}
|
||||
|
||||
-// Deliver a widget pointer
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Get pointer to a GTK widget by \param type.
|
||||
+
|
||||
+ Returns the pointer to a GTK widget, specified by \param type.
|
||||
+ GTK widgets are cached, so that only one instance of each type is created.
|
||||
+ \note
|
||||
+ The method returns nullptr for the enum value gtk_Default.
|
||||
+ */
|
||||
GtkWidget *QGtk3Interface::widget(QGtkWidget type) const
|
||||
{
|
||||
if (type == QGtkWidget::gtk_Default)
|
||||
@@ -371,7 +438,14 @@ GtkWidget *QGtk3Interface::widget(QGtkWidget type) const
|
||||
return w;
|
||||
}
|
||||
|
||||
-// Return widget syle context or default style
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Access a GTK widget's style context.
|
||||
+
|
||||
+ Returns the pointer to the style context of GTK widget \param w.
|
||||
+
|
||||
+ \note If \param w is nullptr, the GTK default style context (entry style) is returned.
|
||||
+ */
|
||||
GtkStyleContext *QGtk3Interface::context(GtkWidget *w) const
|
||||
{
|
||||
if (w)
|
||||
@@ -380,15 +454,28 @@ GtkStyleContext *QGtk3Interface::context(GtkWidget *w) const
|
||||
return gtk_widget_get_style_context(widget(QGtkWidget::gtk_entry));
|
||||
}
|
||||
|
||||
-// FIXME
|
||||
-// Brush assets (e.g. 9-patches) can't be accessed by the GTK API.
|
||||
-// => brush height and width from GTK will be ignored for the time being,
|
||||
-// because it is unknown if they relate to a plain brush or an image brush.
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Create a QBrush from a GTK widget.
|
||||
+
|
||||
+ Returns a QBrush corresponding to GTK widget type \param wtype, \param source and \param state.
|
||||
+
|
||||
+ Brush height and width is ignored in GTK3, because brush assets (e.g. 9-patches)
|
||||
+ can't be accessed by the GTK3 API. It's therefore unknown, if the brush relates only to colors,
|
||||
+ or to a pixmap based style.
|
||||
+
|
||||
+ */
|
||||
QBrush QGtk3Interface::brush(QGtkWidget wtype, QGtkColorSource source, GtkStateFlags state) const
|
||||
{
|
||||
+ // FIXME: When a color's pixmap can be accessed via the GTK API,
|
||||
+ // read it and set it in the brush.
|
||||
return QBrush(color(widget(wtype), source, state));
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Returns the name of the current GTK theme.
|
||||
+ */
|
||||
const QString QGtk3Interface::themeName() const
|
||||
{
|
||||
gchar *theme_name;
|
||||
@@ -400,6 +487,15 @@ const QString QGtk3Interface::themeName() const
|
||||
return QLatin1String(theme_name);
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Determine appearance by colors.
|
||||
+
|
||||
+ Returns the appearance of the current GTK theme, heuristically determined by the
|
||||
+ lightness difference between default background and foreground colors.
|
||||
+
|
||||
+ \note Returns Unknown in the unlikely case that both colors have the same lightness.
|
||||
+ */
|
||||
Qt::Appearance QGtk3Interface::appearanceByColors() const
|
||||
{
|
||||
const QColor background = color(widget(QGtkWidget::gtk_Default),
|
||||
@@ -416,6 +512,12 @@ Qt::Appearance QGtk3Interface::appearanceByColors() const
|
||||
return Qt::Appearance::Unknown;
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Map font type to GTK widget type.
|
||||
+
|
||||
+ Returns the GTK widget type corresponding to the given QPlatformTheme::Font \param type.
|
||||
+ */
|
||||
inline constexpr QGtk3Interface::QGtkWidget QGtk3Interface::toWidgetType(QPlatformTheme::Font type)
|
||||
{
|
||||
switch (type) {
|
||||
@@ -451,6 +553,10 @@ inline constexpr QGtk3Interface::QGtkWidget QGtk3Interface::toWidgetType(QPlatfo
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Convert pango \param style to QFont::Style.
|
||||
+ */
|
||||
inline constexpr QFont::Style QGtk3Interface::toFontStyle(PangoStyle style)
|
||||
{
|
||||
switch (style) {
|
||||
@@ -462,6 +568,13 @@ inline constexpr QFont::Style QGtk3Interface::toFontStyle(PangoStyle style)
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Convert pango font \param weight to an int, representing font weight in Qt.
|
||||
+
|
||||
+ Compatibility of PangoWeight is statically asserted.
|
||||
+ The minimum (1) and maximum (1000) weight in Qt is respeced.
|
||||
+ */
|
||||
inline constexpr int QGtk3Interface::toFontWeight(PangoWeight weight)
|
||||
{
|
||||
// GTK PangoWeight can be directly converted to QFont::Weight
|
||||
@@ -494,6 +607,17 @@ inline constexpr QFont::Weight QGtk3Interface::toQFontWeight(int weight)
|
||||
return QFont::Black;
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Return a GTK styled font.
|
||||
+
|
||||
+ Returns the QFont corresponding to \param type by reading the corresponding
|
||||
+ GTK widget type's font.
|
||||
+
|
||||
+ \note GTK allows to specify a non fixed font as the system's fixed font.
|
||||
+ If a fixed font is requested, the method fixes the pitch and falls back to monospace,
|
||||
+ unless a suitable fixed pitch font is found.
|
||||
+ */
|
||||
QFont QGtk3Interface::font(QPlatformTheme::Font type) const
|
||||
{
|
||||
GtkStyleContext *con = context(widget(toWidgetType(type)));
|
||||
@@ -517,9 +641,6 @@ QFont QGtk3Interface::font(QPlatformTheme::Font type) const
|
||||
font.setPointSizeF(static_cast<float>(pango_font_description_get_size(gtkFont)/PANGO_SCALE));
|
||||
font.setStyle(toFontStyle(pango_font_description_get_style(gtkFont)));
|
||||
|
||||
- // fix pixel pitch if fixed font is requested
|
||||
- // NOTE: GTK allows to specify a non fixed font as the system's fixed font.
|
||||
- // => the returned font may still not be a fixed font.
|
||||
if (type == QPlatformTheme::FixedFont) {
|
||||
font.setFixedPitch(true);
|
||||
if (!QFontInfo(font).fixedPitch()) {
|
||||
@@ -532,6 +653,10 @@ QFont QGtk3Interface::font(QPlatformTheme::Font type) const
|
||||
return font;
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Returns a GTK styled file icon for \param fileInfo.
|
||||
+ */
|
||||
QIcon QGtk3Interface::fileIcon(const QFileInfo &fileInfo) const
|
||||
{
|
||||
GFile *file = g_file_new_for_path(fileInfo.absoluteFilePath().toLatin1().constData());
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3interface_p.h b/src/plugins/platformthemes/gtk3/qgtk3interface_p.h
|
||||
index e04025923d..42643e72ef 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3interface_p.h
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3interface_p.h
|
||||
@@ -36,6 +36,18 @@ QT_BEGIN_NAMESPACE
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcQGtk3Interface);
|
||||
|
||||
class QGtk3Storage;
|
||||
+
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief The QGtk3Interface class centralizes communication with the GTK3 library.
|
||||
+
|
||||
+ By encapsulating all GTK version specific syntax and conversions, it makes Qt's GTK theme
|
||||
+ independent from GTK versions.
|
||||
+
|
||||
+ \note
|
||||
+ Including GTK3 headers requires #undef signals, which disables Qt signal/slot handling.
|
||||
+ */
|
||||
+
|
||||
class QGtk3Interface
|
||||
{
|
||||
Q_GADGET
|
||||
@@ -43,7 +55,13 @@ public:
|
||||
QGtk3Interface(QGtk3Storage *);
|
||||
~QGtk3Interface();
|
||||
|
||||
- // Enum representing GTK widget types
|
||||
+ /*!
|
||||
+ * \internal
|
||||
+ \enum QGtk3Interface::QGtkWidget
|
||||
+ \brief Represents GTK widget types used to obtain color information.
|
||||
+
|
||||
+ \note The enum value gtk_Default refers to the GTK default style, rather than to a specific widget.
|
||||
+ */
|
||||
enum class QGtkWidget {
|
||||
gtk_menu_bar,
|
||||
gtk_menu,
|
||||
@@ -68,7 +86,15 @@ public:
|
||||
};
|
||||
Q_ENUM(QGtkWidget)
|
||||
|
||||
- // Enum representing color sources of a GTK theme
|
||||
+ /*!
|
||||
+ \internal
|
||||
+ \enum QGtk3Interface::QGtkColorSource
|
||||
+ \brief The QGtkColorSource enum represents the source of a color within a GTK widgets style context.
|
||||
+
|
||||
+ If the current GTK theme provides such a color for a given widget, the color can be read
|
||||
+ from the style context by passing the enum's key as a property name to the GTK method
|
||||
+ gtk_style_context_lookup_color. The method will return false, if no color has been found.
|
||||
+ */
|
||||
enum class QGtkColorSource {
|
||||
Foreground,
|
||||
Background,
|
||||
@@ -78,7 +104,18 @@ public:
|
||||
};
|
||||
Q_ENUM(QGtkColorSource)
|
||||
|
||||
- // Enum for default color getter
|
||||
+ /*!
|
||||
+ \internal
|
||||
+ \enum QGtk3Interface::QGtkColorDefault
|
||||
+ \brief The QGtkColorDefault enum represents generic GTK colors.
|
||||
+
|
||||
+ The GTK3 methods gtk_style_context_get_color, gtk_style_context_get_background_color, and
|
||||
+ gtk_style_context_get_foreground_color always return the respective colors with a widget's
|
||||
+ style context. Unless set as a property by the current GTK theme, GTK's default colors will
|
||||
+ be returned.
|
||||
+ These generic default colors, represented by the GtkColorDefault enum, are used as a
|
||||
+ back, if a specific color property is requested but not defined in the current GTK theme.
|
||||
+ */
|
||||
enum class QGtkColorDefault {
|
||||
Foreground,
|
||||
Background,
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,366 @@
|
||||
From f5e74db1b5245814d5993b6b16d58274ca8b89ab Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Thu, 27 Jul 2023 12:42:49 +0200
|
||||
Subject: [PATCH 13/15] Document QGtk3Storage
|
||||
|
||||
Add internal documentation to header and implementation of
|
||||
QGtk3Storage
|
||||
---
|
||||
.../platformthemes/gtk3/qgtk3storage.cpp | 231 +++++++++++++++---
|
||||
.../platformthemes/gtk3/qgtk3storage_p.h | 1 +
|
||||
2 files changed, 193 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
index 0b6b8e8523..7775ac66e4 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
@@ -24,7 +24,26 @@ QGtk3Storage::QGtk3Storage()
|
||||
populateMap();
|
||||
}
|
||||
|
||||
-// Set a brush from a source and resolve recursions
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \enum QGtk3Storage::SourceType
|
||||
+ \brief This enum represents the type of a color source.
|
||||
+
|
||||
+ \value Gtk Color is read from a GTK widget
|
||||
+ \value Fixed A fixed brush is specified
|
||||
+ \value Modified The color is a modification of another color (fixed or read from GTK)
|
||||
+ \omitvalue Invalid
|
||||
+ */
|
||||
+
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Find a brush from a source.
|
||||
+
|
||||
+ Returns a QBrush from a given \param source and a \param map of available brushes
|
||||
+ to search from.
|
||||
+
|
||||
+ A null QBrush is returned, if no brush corresponding to the source has been found.
|
||||
+ */
|
||||
QBrush QGtk3Storage::brush(const Source &source, const BrushMap &map) const
|
||||
{
|
||||
switch (source.sourceType) {
|
||||
@@ -64,7 +83,14 @@ QBrush QGtk3Storage::brush(const Source &source, const BrushMap &map) const
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
-// Find source for a recursion and take dark/light/unknown into consideration
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Recurse to find a source brush for modification.
|
||||
+
|
||||
+ Returns the source specified by the target brush \param b in the \param map of brushes.
|
||||
+ Takes dark/light/unknown into consideration.
|
||||
+ Returns an empty brush if no suitable one can be found.
|
||||
+ */
|
||||
QGtk3Storage::Source QGtk3Storage::brush(const TargetBrush &b, const BrushMap &map) const
|
||||
{
|
||||
#define FIND(brush) if (map.contains(brush))\
|
||||
@@ -88,7 +114,16 @@ QGtk3Storage::Source QGtk3Storage::brush(const TargetBrush &b, const BrushMap &m
|
||||
#undef FIND
|
||||
}
|
||||
|
||||
-// Create a simple standard palette
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Returns a simple, hard coded base palette.
|
||||
+
|
||||
+ Create a hard coded palette with default colors as a fallback for any color that can't be
|
||||
+ obtained from GTK.
|
||||
+
|
||||
+ \note This palette will be used as a default baseline for the system palette, which then
|
||||
+ will be used as a default baseline for any other palette type.
|
||||
+ */
|
||||
QPalette QGtk3Storage::standardPalette()
|
||||
{
|
||||
QColor backgroundColor(0xd4, 0xd0, 0xc8);
|
||||
@@ -105,7 +140,13 @@ QPalette QGtk3Storage::standardPalette()
|
||||
return palette;
|
||||
}
|
||||
|
||||
-// Deliver a palette styled according to the current GTK Theme
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Return a GTK styled QPalette.
|
||||
+
|
||||
+ Returns the pointer to a (cached) QPalette for \param type, with its brushes
|
||||
+ populated according to the current GTK theme.
|
||||
+ */
|
||||
const QPalette *QGtk3Storage::palette(QPlatformTheme::Palette type) const
|
||||
{
|
||||
if (type >= QPlatformTheme::NPalettes)
|
||||
@@ -160,6 +201,12 @@ const QPalette *QGtk3Storage::palette(QPlatformTheme::Palette type) const
|
||||
return &m_paletteCache[type].value();
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Return a GTK styled font.
|
||||
+
|
||||
+ Returns a QFont of \param type, styled according to the current GTK theme.
|
||||
+*/
|
||||
const QFont *QGtk3Storage::font(QPlatformTheme::Font type) const
|
||||
{
|
||||
if (m_fontCache[type].has_value())
|
||||
@@ -169,6 +216,13 @@ const QFont *QGtk3Storage::font(QPlatformTheme::Font type) const
|
||||
return &m_fontCache[type].value();
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Return a GTK styled standard pixmap if available.
|
||||
+
|
||||
+ Returns a pixmap specified by \param standardPixmap and \param size.
|
||||
+ Returns an empty pixmap if GTK doesn't support the requested one.
|
||||
+ */
|
||||
QPixmap QGtk3Storage::standardPixmap(QPlatformTheme::StandardPixmap standardPixmap,
|
||||
const QSizeF &size) const
|
||||
{
|
||||
@@ -186,11 +240,19 @@ QPixmap QGtk3Storage::standardPixmap(QPlatformTheme::StandardPixmap standardPixm
|
||||
return QPixmap::fromImage(image.scaled(size.toSize()));
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Returns a GTK styled file icon corresponding to \param fileInfo.
|
||||
+ */
|
||||
QIcon QGtk3Storage::fileIcon(const QFileInfo &fileInfo) const
|
||||
{
|
||||
return m_interface ? m_interface->fileIcon(fileInfo) : QIcon();
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Clears all caches.
|
||||
+ */
|
||||
void QGtk3Storage::clear()
|
||||
{
|
||||
m_appearance = Qt::Appearance::Unknown;
|
||||
@@ -202,6 +264,13 @@ void QGtk3Storage::clear()
|
||||
cache.reset();
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Handles a theme change at runtime.
|
||||
+
|
||||
+ Clear all caches, re-populate with current GTK theme and notify the window system interface.
|
||||
+ This method is a callback for the theme change signal sent from GTK.
|
||||
+ */
|
||||
void QGtk3Storage::handleThemeChange()
|
||||
{
|
||||
clear();
|
||||
@@ -209,6 +278,54 @@ void QGtk3Storage::handleThemeChange()
|
||||
QWindowSystemInterface::handleThemeChange(nullptr);
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Populates a map with information about how to locate colors in GTK.
|
||||
+
|
||||
+ This method creates a data structure to locate color information for each brush of a QPalette
|
||||
+ within GTK. The structure can hold mapping information for each QPlatformTheme::Palette
|
||||
+ enum value. If no specific mapping is stored for an enum value, the system palette is returned
|
||||
+ instead of a specific one. If no mapping is stored for the system palette, it will fall back to
|
||||
+ QGtk3Storage::standardPalette.
|
||||
+
|
||||
+ The method will populate the data structure with a standard mapping, covering the following
|
||||
+ palette types:
|
||||
+ \list
|
||||
+ \li QPlatformTheme::SystemPalette
|
||||
+ \li QPlatformTheme::CheckBoxPalette
|
||||
+ \li QPlatformTheme::RadioButtonPalette
|
||||
+ \li QPlatformTheme::ComboBoxPalette
|
||||
+ \li QPlatformTheme::GroupBoxPalette
|
||||
+ \li QPlatformTheme::MenuPalette
|
||||
+ \li QPlatformTheme::TextLineEditPalette
|
||||
+ \endlist
|
||||
+
|
||||
+ The method will check the environment variable {{QT_GUI_GTK_JSON_SAVE}}. If it points to a
|
||||
+ valid path with write access, it will write the standard mapping into a Json file.
|
||||
+ That Json file can be modified and/or extended.
|
||||
+ The Json syntax is
|
||||
+ - "QGtk3Palettes" (top level value)
|
||||
+ - QPlatformTheme::Palette
|
||||
+ - QPalette::ColorRole
|
||||
+ - Qt::Appearance
|
||||
+ - Qt::ColorGroup
|
||||
+ - Source data
|
||||
+ - Source Type
|
||||
+ - [source data]
|
||||
+
|
||||
+ If the environment variable {{QT_GUI_GTK_JSON_HARDCODED}} contains the keyword \c true,
|
||||
+ all sources are converted to fixed sources. In that case, they contain the hard coded HexRGBA
|
||||
+ values read from GTK.
|
||||
+
|
||||
+ The method will also check the environment variable {{QT_GUI_GTK_JSON}}. If it points to a valid
|
||||
+ Json file with read access, it will be parsed instead of creating a standard mapping.
|
||||
+ Parsing errors will be printed out with qCInfo if the logging category {{qt.qpa.gtk}} is activated.
|
||||
+ In case of a parsing error, the method will fall back to creating a standard mapping.
|
||||
+
|
||||
+ \note
|
||||
+ If a Json file contains only fixed brushes (e.g. exported with {{QT_GUI_GTK_JSON_HARDCODED=true}}),
|
||||
+ no colors will be imported from GTK.
|
||||
+ */
|
||||
void QGtk3Storage::populateMap()
|
||||
{
|
||||
static QString m_themeName;
|
||||
@@ -248,6 +365,15 @@ void QGtk3Storage::populateMap()
|
||||
qWarning() << "File" << jsonOutput << "could not be saved.\n";
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Return a palette map for saving.
|
||||
+
|
||||
+ This method returns the existing palette map, if the environment variable
|
||||
+ {{QT_GUI_GTK_JSON_HARDCODED}} is not set or does not contain the keyword \c true.
|
||||
+ If it contains the keyword \c true, it returns a palette map with all brush
|
||||
+ sources converted to fixed sources.
|
||||
+ */
|
||||
const QGtk3Storage::PaletteMap QGtk3Storage::savePalettes() const
|
||||
{
|
||||
const QString hard = qEnvironmentVariable("QT_GUI_GTK_JSON_HARDCODED");
|
||||
@@ -282,21 +408,50 @@ const QGtk3Storage::PaletteMap QGtk3Storage::savePalettes() const
|
||||
return map;
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Saves current palette mapping to a \param filename with Json format \param f.
|
||||
+
|
||||
+ Saves the current palette mapping into a QJson file,
|
||||
+ taking {{QT_GUI_GTK_JSON_HARDCODED}} into consideration.
|
||||
+ Returns \c true if saving was successful and \c false otherwise.
|
||||
+ */
|
||||
bool QGtk3Storage::save(const QString &filename, QJsonDocument::JsonFormat f) const
|
||||
{
|
||||
return QGtk3Json::save(savePalettes(), filename, f);
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Returns a QJsonDocument with current palette mapping.
|
||||
+
|
||||
+ Saves the current palette mapping into a QJsonDocument,
|
||||
+ taking {{QT_GUI_GTK_JSON_HARDCODED}} into consideration.
|
||||
+ Returns \c true if saving was successful and \c false otherwise.
|
||||
+ */
|
||||
QJsonDocument QGtk3Storage::save() const
|
||||
{
|
||||
return QGtk3Json::save(savePalettes());
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Loads palette mapping from Json file \param filename.
|
||||
+
|
||||
+ Returns \c true if the file was successfully parsed and \c false otherwise.
|
||||
+ */
|
||||
bool QGtk3Storage::load(const QString &filename)
|
||||
{
|
||||
return QGtk3Json::load(m_palettes, filename);
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief Creates a standard palette mapping.
|
||||
+
|
||||
+ The method creates a hard coded standard mapping, used if no external Json file
|
||||
+ containing a valid mapping has been specified in the environment variable {{QT_GUI_GTK_JSON}}.
|
||||
+ */
|
||||
void QGtk3Storage::createMapping()
|
||||
{
|
||||
// Hard code standard mapping
|
||||
@@ -332,41 +487,39 @@ void QGtk3Storage::createMapping()
|
||||
#define CLEAR map.clear()
|
||||
|
||||
/*
|
||||
- * Macro ussage:
|
||||
- *
|
||||
- * 1. Define a source
|
||||
- *
|
||||
- * GTK(QGtkWidget, QGtkColorSource, GTK_STATE_FLAG)
|
||||
- * Fetch the color from a GtkWidget, related to a source and a state.
|
||||
- *
|
||||
- * LIGHTER(ColorGroup, ColorROle, lighter)
|
||||
- * Use a color of the same QPalette related to ColorGroup and ColorRole.
|
||||
- * Make the color lighter (if lighter >100) or darker (if lighter < 100)
|
||||
- *
|
||||
- * MODIFY(ColorGroup, ColorRole, red, green, blue)
|
||||
- * Use a color of the same QPalette related to ColorGroup and ColorRole.
|
||||
- * Modify it by adding red, green, blue.
|
||||
- *
|
||||
- * FIX(const QBrush &)
|
||||
- * Use a fixed brush without querying GTK
|
||||
- *
|
||||
- * 2. Define the target
|
||||
- *
|
||||
- * Use ADD(ColorGroup, ColorRole) to use the defined source for the
|
||||
- * color group / role in the current palette.
|
||||
- *
|
||||
- * Use ADD(ColorGroup, ColorRole, Appearance) to use the defined source
|
||||
- * only for a specific appearance
|
||||
- *
|
||||
- * 3. Save mapping
|
||||
- * Save the defined mappings for a specific palette.
|
||||
- * If a mapping entry does not cover all color groups and roles of a palette,
|
||||
- * the system palette will be used for the remaining values.
|
||||
- * If the system palette does not have all combination of color groups and roles,
|
||||
- * the remaining ones will be populated by a hard coded fusion-style like palette.
|
||||
- *
|
||||
- * 4. Clear mapping
|
||||
- * Use CLEAR to clear the mapping and begin a new one.
|
||||
+ Macro usage:
|
||||
+
|
||||
+ 1. Define a source
|
||||
+ GTK(QGtkWidget, QGtkColorSource, GTK_STATE_FLAG)
|
||||
+ Fetch the color from a GtkWidget, related to a source and a state.
|
||||
+
|
||||
+ LIGHTER(ColorGroup, ColorROle, lighter)
|
||||
+ Use a color of the same QPalette related to ColorGroup and ColorRole.
|
||||
+ Make the color lighter (if lighter >100) or darker (if lighter < 100)
|
||||
+
|
||||
+ MODIFY(ColorGroup, ColorRole, red, green, blue)
|
||||
+ Use a color of the same QPalette related to ColorGroup and ColorRole.
|
||||
+ Modify it by adding red, green, blue.
|
||||
+
|
||||
+ FIX(const QBrush &)
|
||||
+ Use a fixed brush without querying GTK
|
||||
+
|
||||
+ 2. Define the target
|
||||
+ Use ADD(ColorGroup, ColorRole) to use the defined source for the
|
||||
+ color group / role in the current palette.
|
||||
+
|
||||
+ Use ADD(ColorGroup, ColorRole, Appearance) to use the defined source
|
||||
+ only for a specific appearance
|
||||
+
|
||||
+ 3. Save mapping
|
||||
+ Save the defined mappings for a specific palette.
|
||||
+ If a mapping entry does not cover all color groups and roles of a palette,
|
||||
+ the system palette will be used for the remaining values.
|
||||
+ If the system palette does not have all combination of color groups and roles,
|
||||
+ the remaining ones will be populated by a hard coded fusion-style like palette.
|
||||
+
|
||||
+ 4. Clear mapping
|
||||
+ Use CLEAR to clear the mapping and begin a new one.
|
||||
*/
|
||||
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3storage_p.h b/src/plugins/platformthemes/gtk3/qgtk3storage_p.h
|
||||
index 57f6aeea96..af628d49ff 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3storage_p.h
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3storage_p.h
|
||||
@@ -33,6 +33,7 @@ class QGtk3Storage
|
||||
public:
|
||||
QGtk3Storage();
|
||||
|
||||
+ // Enum documented in cpp file. Please keep it in line with updates made here.
|
||||
enum class SourceType {
|
||||
Gtk,
|
||||
Fixed,
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,84 @@
|
||||
From 9628ad303ad924255a224fdcc113ff8264172fc7 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Thu, 27 Jul 2023 12:44:11 +0200
|
||||
Subject: [PATCH 14/15] QGtk3Theme: Improve fixed font delivery
|
||||
|
||||
The gtk_fixed widget was used as a reference to obtain a fixed font
|
||||
and HeaderViewFont.
|
||||
|
||||
This is a mistake, because the gtk_fixed widget is a container for
|
||||
other widgets with fixed geometries and no layouting.
|
||||
|
||||
This patch makes the default style being used for a fixed font and, as
|
||||
a drive-by, the combo box as a reference for a header view font.
|
||||
A monospace based css provider as explicitly added to the style
|
||||
context, in case a fixed font is requested. The provider is removed
|
||||
afterwards.
|
||||
---
|
||||
.../platformthemes/gtk3/qgtk3interface.cpp | 24 +++++++++++++++++--
|
||||
1 file changed, 22 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3interface.cpp b/src/plugins/platformthemes/gtk3/qgtk3interface.cpp
|
||||
index 0fab1220b4..21abea81cf 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3interface.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3interface.cpp
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <QtCore/QMetaEnum>
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtCore/QFileInfo>
|
||||
+#include <QtCore/QScopeGuard>
|
||||
#include <QtGui/QFontDatabase>
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
@@ -538,13 +539,13 @@ inline constexpr QGtk3Interface::QGtkWidget QGtk3Interface::toWidgetType(QPlatfo
|
||||
case QPlatformTheme::ToolButtonFont: return QGtkWidget::gtk_button;
|
||||
case QPlatformTheme::ItemViewFont: return QGtkWidget::gtk_entry;
|
||||
case QPlatformTheme::ListViewFont: return QGtkWidget::gtk_tree_view;
|
||||
- case QPlatformTheme::HeaderViewFont: return QGtkWidget::gtk_fixed;
|
||||
+ case QPlatformTheme::HeaderViewFont: return QGtkWidget::gtk_combo_box;
|
||||
case QPlatformTheme::ListBoxFont: return QGtkWidget::gtk_Default;
|
||||
case QPlatformTheme::ComboMenuItemFont: return QGtkWidget::gtk_combo_box;
|
||||
case QPlatformTheme::ComboLineEditFont: return QGtkWidget::gtk_combo_box_text;
|
||||
case QPlatformTheme::SmallFont: return QGtkWidget::gtk_Default;
|
||||
case QPlatformTheme::MiniFont: return QGtkWidget::gtk_Default;
|
||||
- case QPlatformTheme::FixedFont: return QGtkWidget::gtk_fixed;
|
||||
+ case QPlatformTheme::FixedFont: return QGtkWidget::gtk_Default;
|
||||
case QPlatformTheme::GroupBoxTitleFont: return QGtkWidget::gtk_Default;
|
||||
case QPlatformTheme::TabButtonFont: return QGtkWidget::gtk_button;
|
||||
case QPlatformTheme::EditorFont: return QGtkWidget::gtk_entry;
|
||||
@@ -624,6 +625,24 @@ QFont QGtk3Interface::font(QPlatformTheme::Font type) const
|
||||
if (!con)
|
||||
return QFont();
|
||||
|
||||
+ // explicitly add provider for fixed font
|
||||
+ GtkCssProvider *cssProvider = nullptr;
|
||||
+ if (type == QPlatformTheme::FixedFont) {
|
||||
+ cssProvider = gtk_css_provider_new();
|
||||
+ const char *fontSpec = "{font-family: monospace;}";
|
||||
+ gtk_css_provider_load_from_data(cssProvider, fontSpec, -1, NULL);
|
||||
+ gtk_style_context_add_provider(con, GTK_STYLE_PROVIDER(cssProvider),
|
||||
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||
+ }
|
||||
+
|
||||
+ // remove monospace provider from style context and unref it
|
||||
+ QScopeGuard guard([&](){
|
||||
+ if (cssProvider) {
|
||||
+ gtk_style_context_remove_provider(con, GTK_STYLE_PROVIDER(cssProvider));
|
||||
+ g_object_unref(cssProvider);
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
const PangoFontDescription *gtkFont = gtk_style_context_get_font(con, GTK_STATE_FLAG_NORMAL);
|
||||
if (!gtkFont)
|
||||
return QFont();
|
||||
@@ -650,6 +669,7 @@ QFont QGtk3Interface::font(QPlatformTheme::Font type) const
|
||||
font.setFamily("monospace");
|
||||
}
|
||||
}
|
||||
+
|
||||
return font;
|
||||
}
|
||||
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,56 @@
|
||||
From 6a9a896ae86a69a3c8bcbaaf7e2e2fd2105723a4 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <jgrulich@redhat.com>
|
||||
Date: Thu, 27 Jul 2023 12:44:31 +0200
|
||||
Subject: [PATCH 15/15] QGtk3Theme: Do not default Active WindowText to button
|
||||
foreground
|
||||
|
||||
QGtk3Theme uses the GTK button foreground as a default for the
|
||||
WindowText color role. When a GTK3 theme has no specific color for the
|
||||
entry text, this can lead to text on certain assets looking darker
|
||||
and thus disabled.
|
||||
|
||||
This discontinues usage of the button foreground for the window text.
|
||||
|
||||
Finding the WindowText color role in QPlatformTheme::SystemPalette now
|
||||
follows the following logic:
|
||||
(1) GTK normal entry text is used if specified. This is the preferred
|
||||
option, copying GTK behavior.
|
||||
(2) If (1) is not specified, the GTK default text color is used, making
|
||||
WindowText equal to Text.
|
||||
(3) If neither (1), nor (2) are specified, the WindowText color role is
|
||||
taken from qt_fusionPalette, where it is also equal to Text.
|
||||
|
||||
The SystemPalette is used as a default template for all other control
|
||||
or widget speicific palettes. The rules above therefor apply to all
|
||||
screen assets (unless they use a JSON file to specify a their
|
||||
individual WindowText).
|
||||
|
||||
[ChangeLog][QGtk3Theme][SystemPalette][WindowText] Default to GTK
|
||||
Entry Text / Normal Text / qt_fusionPalette
|
||||
---
|
||||
src/plugins/platformthemes/gtk3/qgtk3storage.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
index 7775ac66e4..fb4069ba3c 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
@@ -538,7 +538,6 @@ void QGtk3Storage::createMapping()
|
||||
LIGHTER(Normal, Window, 80);
|
||||
ADD(Normal, Dark);
|
||||
GTK(button, Foreground, ACTIVE);
|
||||
- ADD(Normal, WindowText);
|
||||
ADD(Inactive, WindowText);
|
||||
LIGHTER(Normal, WindowText, 50);
|
||||
ADD(Disabled, Text);
|
||||
@@ -562,6 +561,7 @@ void QGtk3Storage::createMapping()
|
||||
ADD(Disabled, HighlightedText);
|
||||
GTK(Default, Text, NORMAL);
|
||||
ADD(Normal, Text);
|
||||
+ ADD(Normal, WindowText);
|
||||
ADD(Inactive, Text);
|
||||
ADD(Normal, HighlightedText);
|
||||
LIGHTER(Normal, Base, 93);
|
||||
--
|
||||
2.41.0
|
||||
|
@ -0,0 +1,52 @@
|
||||
From 233e7e6be35a5a455b6ecd7c15de8c9cfc70ca10 Mon Sep 17 00:00:00 2001
|
||||
From: Thorbjørn Lindeijer <bjorn@lindeijer.nl>
|
||||
Date: Thu, 3 Aug 2023 16:09:49 +0200
|
||||
Subject: Fix memory leak in QGtk3Interface::themeName
|
||||
|
||||
Pick-to: 6.6 6.5
|
||||
Change-Id: Ib8c90f7ef66c095f0c1fc04f4cc72bf5eea72ddb
|
||||
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3interface.cpp b/src/plugins/platformthemes/gtk3/qgtk3interface.cpp
|
||||
index 21abea81..8e8fefb6 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3interface.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3interface.cpp
|
||||
@@ -477,15 +477,18 @@ QBrush QGtk3Interface::brush(QGtkWidget wtype, QGtkColorSource source, GtkStateF
|
||||
\internal
|
||||
\brief Returns the name of the current GTK theme.
|
||||
*/
|
||||
-const QString QGtk3Interface::themeName() const
|
||||
+QString QGtk3Interface::themeName() const
|
||||
{
|
||||
- gchar *theme_name;
|
||||
- GtkSettings *settings = gtk_settings_get_default();
|
||||
- if (!settings)
|
||||
- return QString();
|
||||
+ QString name;
|
||||
+
|
||||
+ if (GtkSettings *settings = gtk_settings_get_default()) {
|
||||
+ gchar *theme_name;
|
||||
+ g_object_get(settings, "gtk-theme-name", &theme_name, nullptr);
|
||||
+ name = QLatin1String(theme_name);
|
||||
+ g_free(theme_name);
|
||||
+ }
|
||||
|
||||
- g_object_get(settings, "gtk-theme-name", &theme_name, nullptr);
|
||||
- return QLatin1String(theme_name);
|
||||
+ return name;
|
||||
}
|
||||
|
||||
/*!
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3interface_p.h b/src/plugins/platformthemes/gtk3/qgtk3interface_p.h
|
||||
index 42643e72..d9bf5c32 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3interface_p.h
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3interface_p.h
|
||||
@@ -132,7 +132,7 @@ public:
|
||||
QIcon fileIcon(const QFileInfo &fileInfo) const;
|
||||
|
||||
// Return current GTK theme name
|
||||
- const QString themeName() const;
|
||||
+ QString themeName() const;
|
||||
|
||||
// Derive appearance from default colors
|
||||
Qt::Appearance appearanceByColors() const;
|
@ -0,0 +1,40 @@
|
||||
From 4cffb3b5fbbad24fed26690c3e10c0332cb0b33f Mon Sep 17 00:00:00 2001
|
||||
From: Santhosh Kumar <santhosh.kumar.selvaraj@qt.io>
|
||||
Date: Mon, 9 Oct 2023 13:17:19 +0200
|
||||
Subject: Fix disabled button color in Linux (X11/Wayland)
|
||||
|
||||
The palette mapping table (as read from gtk widget) maintained in
|
||||
QGtk3Storage misses information of QPalette::Button and
|
||||
QPalette::ButtonText role for QPalette::Disabled color group. This
|
||||
cause disabled button widget to be rendered with incorrect palette
|
||||
(such as in dark color scheme, light palette had been used).
|
||||
|
||||
This patch fixes this issue by extending palette mapping in
|
||||
QGtk3Storage for disabled color group of button role.
|
||||
|
||||
Fixes: QTBUG-113486
|
||||
Pick-to: 6.6.0 6.6 6.5
|
||||
Change-Id: Ied4b2650c92cc1cda58be69257945991013b276f
|
||||
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
index 1952ce278c..0017f55a45 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
@@ -531,6 +531,8 @@ void QGtk3Storage::createMapping()
|
||||
ADD(Normal, Base);
|
||||
ADD(Inactive, Base);
|
||||
ADD(Inactive, Window);
|
||||
+ ADD(Disabled, Button);
|
||||
+ ADD(Disabled, Window);
|
||||
LIGHTER(Normal, Window, 125);
|
||||
ADD(Normal, Light);
|
||||
LIGHTER(Normal, Window, 70);
|
||||
@@ -543,6 +545,7 @@ void QGtk3Storage::createMapping()
|
||||
ADD(Disabled, Text);
|
||||
ADD(Disabled, WindowText);
|
||||
ADD(Inactive, ButtonText);
|
||||
+ ADD(Disabled, ButtonText);
|
||||
GTK(button, Text, NORMAL);
|
||||
ADD(Disabled, ButtonText);
|
||||
// special background colors
|
@ -0,0 +1,241 @@
|
||||
From a608a7c29886fd95ea8569776036673e6c7639f2 Mon Sep 17 00:00:00 2001
|
||||
From: Santhosh Kumar <santhosh.kumar.selvaraj@qt.io>
|
||||
Date: Tue, 10 Oct 2023 16:07:07 +0200
|
||||
Subject: Fix inactive palette in gtk3 theme
|
||||
|
||||
In gtk3 theme, the inactive color group had been set with incorrect
|
||||
palette or not been set for some cases, which leads to glitch when
|
||||
moving application window. This is because inactive group palettes were
|
||||
applied during window movement and its expected to be set with correct
|
||||
palettes.
|
||||
|
||||
This patch fixes this issue by setting correct palette for inactive
|
||||
color group.
|
||||
|
||||
Fixes: QTBUG-112879
|
||||
Pick-to: 6.6 6.5
|
||||
Change-Id: I6658843626f322fee0ef99dfafb550956e3e0aee
|
||||
Reviewed-by: Jonas Karlsson <jonas.karlsson@qt.io>
|
||||
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
index 0017f55a45..bbc70c39a2 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
@@ -524,93 +524,129 @@ void QGtk3Storage::createMapping()
|
||||
|
||||
|
||||
// System palette
|
||||
- // background color and calculate derivates
|
||||
- GTK(Default, Background, INSENSITIVE);
|
||||
- ADD(Normal, Window);
|
||||
- ADD(Normal, Button);
|
||||
- ADD(Normal, Base);
|
||||
- ADD(Inactive, Base);
|
||||
- ADD(Inactive, Window);
|
||||
- ADD(Disabled, Button);
|
||||
- ADD(Disabled, Window);
|
||||
- LIGHTER(Normal, Window, 125);
|
||||
- ADD(Normal, Light);
|
||||
- LIGHTER(Normal, Window, 70);
|
||||
- ADD(Normal, Shadow);
|
||||
- LIGHTER(Normal, Window, 80);
|
||||
- ADD(Normal, Dark);
|
||||
- GTK(button, Foreground, ACTIVE);
|
||||
- ADD(Inactive, WindowText);
|
||||
- LIGHTER(Normal, WindowText, 50);
|
||||
- ADD(Disabled, Text);
|
||||
- ADD(Disabled, WindowText);
|
||||
- ADD(Inactive, ButtonText);
|
||||
- ADD(Disabled, ButtonText);
|
||||
- GTK(button, Text, NORMAL);
|
||||
- ADD(Disabled, ButtonText);
|
||||
- // special background colors
|
||||
- GTK(Default, Background, SELECTED);
|
||||
- ADD(Disabled, Highlight);
|
||||
- ADD(Normal, Highlight);
|
||||
- GTK(entry, Foreground, SELECTED);
|
||||
- ADD(Normal, HighlightedText);
|
||||
- GTK(entry, Background, ACTIVE);
|
||||
- ADD(Inactive, HighlightedText);
|
||||
- // text color and friends
|
||||
- GTK(entry, Text, NORMAL);
|
||||
- ADD(Normal, ButtonText);
|
||||
- ADD(Normal, WindowText);
|
||||
- ADD(Disabled, WindowText);
|
||||
- ADD(Disabled, HighlightedText);
|
||||
- GTK(Default, Text, NORMAL);
|
||||
- ADD(Normal, Text);
|
||||
- ADD(Normal, WindowText);
|
||||
- ADD(Inactive, Text);
|
||||
- ADD(Normal, HighlightedText);
|
||||
- LIGHTER(Normal, Base, 93);
|
||||
- ADD(All, AlternateBase);
|
||||
- GTK(Default, Foreground, NORMAL);
|
||||
- ADD(All, ToolTipText);
|
||||
- MODIFY(Normal, Text, 100, 100, 100);
|
||||
- ADD(All, PlaceholderText, Light);
|
||||
- MODIFY(Normal, Text, -100, -100, -100);
|
||||
- ADD(All, PlaceholderText, Dark);
|
||||
- SAVE(SystemPalette);
|
||||
- CLEAR;
|
||||
-
|
||||
- // Checkbox and Radio Button
|
||||
- GTK(button, Text, ACTIVE);
|
||||
- ADD(Normal, Base, Dark);
|
||||
- GTK(Default, Background, NORMAL);
|
||||
- ADD(All, Base);
|
||||
- GTK(button, Text, NORMAL);
|
||||
- ADD(Normal, Base, Light);
|
||||
- SAVE(CheckBoxPalette);
|
||||
- SAVE(RadioButtonPalette);
|
||||
- CLEAR;
|
||||
-
|
||||
- // ComboBox, GroupBox, Frame
|
||||
- GTK(combo_box, Text, NORMAL);
|
||||
- ADD(Normal, ButtonText, Dark);
|
||||
- ADD(Normal, Text, Dark);
|
||||
- GTK(combo_box, Text, ACTIVE);
|
||||
- ADD(Normal, ButtonText, Light);
|
||||
- ADD(Normal, Text, Light);
|
||||
- SAVE(ComboBoxPalette);
|
||||
- SAVE(GroupBoxPalette);
|
||||
- CLEAR;
|
||||
-
|
||||
- // Menu bar
|
||||
- GTK(Default, Text, ACTIVE);
|
||||
- ADD(Normal, ButtonText);
|
||||
- SAVE(MenuPalette);
|
||||
- CLEAR;
|
||||
-
|
||||
- // LineEdit
|
||||
- GTK(Default, Background, NORMAL);
|
||||
- ADD(All, Base);
|
||||
- SAVE(TextLineEditPalette);
|
||||
- CLEAR;
|
||||
+ {
|
||||
+ // background color and calculate derivates
|
||||
+ GTK(Default, Background, INSENSITIVE);
|
||||
+ ADD(All, Window);
|
||||
+ ADD(All, Button);
|
||||
+ ADD(All, Base);
|
||||
+ LIGHTER(Normal, Window, 125);
|
||||
+ ADD(Normal, Light);
|
||||
+ ADD(Inactive, Light);
|
||||
+ LIGHTER(Normal, Window, 70);
|
||||
+ ADD(Normal, Shadow);
|
||||
+ LIGHTER(Normal, Window, 80);
|
||||
+ ADD(Normal, Dark);
|
||||
+ ADD(Inactive, Dark)
|
||||
+
|
||||
+ GTK(button, Foreground, ACTIVE);
|
||||
+ ADD(Inactive, WindowText);
|
||||
+ LIGHTER(Normal, WindowText, 50);
|
||||
+ ADD(Disabled, Text);
|
||||
+ ADD(Disabled, WindowText);
|
||||
+ ADD(Disabled, ButtonText);
|
||||
+
|
||||
+ GTK(button, Text, NORMAL);
|
||||
+ ADD(Inactive, ButtonText);
|
||||
+
|
||||
+ // special background colors
|
||||
+ GTK(Default, Background, SELECTED);
|
||||
+ ADD(Disabled, Highlight);
|
||||
+ ADD(Normal, Highlight);
|
||||
+ ADD(Inactive, Highlight);
|
||||
+
|
||||
+ GTK(entry, Foreground, SELECTED);
|
||||
+ ADD(Normal, HighlightedText);
|
||||
+ ADD(Inactive, HighlightedText);
|
||||
+
|
||||
+ // text color and friends
|
||||
+ GTK(entry, Text, NORMAL);
|
||||
+ ADD(Normal, ButtonText);
|
||||
+ ADD(Normal, WindowText);
|
||||
+ ADD(Disabled, HighlightedText);
|
||||
+
|
||||
+ GTK(Default, Text, NORMAL);
|
||||
+ ADD(Normal, Text);
|
||||
+ ADD(Inactive, Text);
|
||||
+ ADD(Normal, HighlightedText);
|
||||
+ LIGHTER(Normal, Base, 93);
|
||||
+ ADD(All, AlternateBase);
|
||||
+
|
||||
+ GTK(Default, Foreground, NORMAL);
|
||||
+ ADD(All, ToolTipText);
|
||||
+ MODIFY(Normal, Text, 100, 100, 100);
|
||||
+ ADD(All, PlaceholderText, Light);
|
||||
+ MODIFY(Normal, Text, -100, -100, -100);
|
||||
+ ADD(All, PlaceholderText, Dark);
|
||||
+
|
||||
+ SAVE(SystemPalette);
|
||||
+ CLEAR;
|
||||
+ }
|
||||
+
|
||||
+ // Label and TabBar Palette
|
||||
+ {
|
||||
+ GTK(entry, Text, NORMAL);
|
||||
+ ADD(Normal, WindowText);
|
||||
+ ADD(Inactive, WindowText);
|
||||
+
|
||||
+ SAVE(LabelPalette);
|
||||
+ SAVE(TabBarPalette);
|
||||
+ CLEAR;
|
||||
+ }
|
||||
+
|
||||
+ // Checkbox and RadioButton Palette
|
||||
+ {
|
||||
+ GTK(button, Text, ACTIVE);
|
||||
+ ADD(Normal, Base, Dark);
|
||||
+ ADD(Inactive, WindowText, Dark);
|
||||
+
|
||||
+ GTK(Default, Foreground, NORMAL);
|
||||
+ ADD(All, Text);
|
||||
+
|
||||
+ GTK(Default, Background, NORMAL);
|
||||
+ ADD(All, Base);
|
||||
+
|
||||
+ GTK(button, Text, NORMAL);
|
||||
+ ADD(Normal, Base, Light);
|
||||
+ ADD(Inactive, WindowText, Light);
|
||||
+
|
||||
+ SAVE(CheckBoxPalette);
|
||||
+ SAVE(RadioButtonPalette);
|
||||
+ CLEAR;
|
||||
+ }
|
||||
+
|
||||
+ // ComboBox, GroupBox & Frame Palette
|
||||
+ {
|
||||
+ GTK(combo_box, Text, NORMAL);
|
||||
+ ADD(Normal, ButtonText, Dark);
|
||||
+ ADD(Normal, Text, Dark);
|
||||
+ ADD(Inactive, WindowText, Dark);
|
||||
+
|
||||
+ GTK(combo_box, Text, ACTIVE);
|
||||
+ ADD(Normal, ButtonText, Light);
|
||||
+ ADD(Normal, Text, Light);
|
||||
+ ADD(Inactive, WindowText, Light);
|
||||
+
|
||||
+ SAVE(ComboBoxPalette);
|
||||
+ SAVE(GroupBoxPalette);
|
||||
+ CLEAR;
|
||||
+ }
|
||||
+
|
||||
+ // MenuBar Palette
|
||||
+ {
|
||||
+ GTK(Default, Text, ACTIVE);
|
||||
+ ADD(Normal, ButtonText);
|
||||
+ SAVE(MenuPalette);
|
||||
+ CLEAR;
|
||||
+ }
|
||||
+
|
||||
+ // LineEdit Palette
|
||||
+ {
|
||||
+ GTK(Default, Background, NORMAL);
|
||||
+ ADD(All, Base);
|
||||
+ SAVE(TextLineEditPalette);
|
||||
+ CLEAR;
|
||||
+ }
|
||||
|
||||
#undef GTK
|
||||
#undef REC
|
@ -0,0 +1,27 @@
|
||||
From 756857b5d05fe85ea93851111fafc430944dbe61 Mon Sep 17 00:00:00 2001
|
||||
From: Santhosh Kumar <santhosh.kumar.selvaraj@qt.io>
|
||||
Date: Wed, 18 Oct 2023 11:23:20 +0200
|
||||
Subject: Fix tooltip palette issue in gtk3 theme
|
||||
|
||||
The tooltip text doesn't show with right palette when application runs
|
||||
in dark mode using gtk3 theme.
|
||||
|
||||
This patchset removes explicitly setting ToolTipText palette in
|
||||
gtk3theme.
|
||||
|
||||
Pick-to: 6.6 6.5
|
||||
Change-Id: Id90626a377733814c3f32f0bf7e5539097b76dd6
|
||||
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
index bbc70c39a2..22cfabb843 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
@@ -573,7 +573,6 @@ void QGtk3Storage::createMapping()
|
||||
ADD(All, AlternateBase);
|
||||
|
||||
GTK(Default, Foreground, NORMAL);
|
||||
- ADD(All, ToolTipText);
|
||||
MODIFY(Normal, Text, 100, 100, 100);
|
||||
ADD(All, PlaceholderText, Light);
|
||||
MODIFY(Normal, Text, -100, -100, -100);
|
@ -0,0 +1,40 @@
|
||||
From fd09519bbd4e7ea89b898c7496e7e06980ee9672 Mon Sep 17 00:00:00 2001
|
||||
From: Axel Spoerl <axel.spoerl@qt.io>
|
||||
Date: Thu, 19 Oct 2023 15:19:12 +0200
|
||||
Subject: QGtk3Theme: define light, midlight, mid, dark and shadow colors
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Define color groups used for shading and in order to render specific
|
||||
inactive texts, e.g. menu item text.
|
||||
|
||||
Found-by: Piotr Wierciński <piotr.wiercinski@qt.io>
|
||||
Pick-to: 6.6 6.5
|
||||
Change-Id: I736f5aff1ff5379ce3f78b53e547b0b5f552779f
|
||||
Reviewed-by: Santhosh Kumar <santhosh.kumar.selvaraj@qt.io>
|
||||
Reviewed-by: Piotr Wierciński <piotr.wiercinski@qt.io>
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
index 22cfabb843..90c0282651 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp
|
||||
@@ -578,6 +578,18 @@ void QGtk3Storage::createMapping()
|
||||
MODIFY(Normal, Text, -100, -100, -100);
|
||||
ADD(All, PlaceholderText, Dark);
|
||||
|
||||
+ // Light, midlight, dark, mid, shadow colors
|
||||
+ LIGHTER(Normal, Button, 125);
|
||||
+ ADD(All, Light)
|
||||
+ LIGHTER(Normal, Button, 113);
|
||||
+ ADD(All, Midlight)
|
||||
+ LIGHTER(Normal, Button, 113);
|
||||
+ ADD(All, Mid)
|
||||
+ LIGHTER(Normal, Button, 87);
|
||||
+ ADD(All, Dark)
|
||||
+ LIGHTER(Normal, Button, 5);
|
||||
+ ADD(All, Shadow)
|
||||
+
|
||||
SAVE(SystemPalette);
|
||||
CLEAR;
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
--- a/src/network/access/qhsts.cpp
|
||||
+++ b/src/network/access/qhsts.cpp
|
||||
@@ -364,8 +364,8 @@ quoted-pair = "\" CHAR
|
||||
bool QHstsHeaderParser::parse(const QList<QPair<QByteArray, QByteArray>> &headers)
|
||||
{
|
||||
for (const auto &h : headers) {
|
||||
- // We use '==' since header name was already 'trimmed' for us:
|
||||
- if (h.first == "Strict-Transport-Security") {
|
||||
+ // We compare directly because header name was already 'trimmed' for us:
|
||||
+ if (h.first.compare("Strict-Transport-Security", Qt::CaseInsensitive) == 0) {
|
||||
header = h.second;
|
||||
// RFC6797, 8.1:
|
||||
//
|
@ -1,49 +0,0 @@
|
||||
diff --git a/src/gui/painting/qfixed_p.h b/src/gui/painting/qfixed_p.h
|
||||
index 84659288..57d750a4 100644
|
||||
--- a/src/gui/painting/qfixed_p.h
|
||||
+++ b/src/gui/painting/qfixed_p.h
|
||||
@@ -54,6 +54,7 @@
|
||||
#include <QtGui/private/qtguiglobal_p.h>
|
||||
#include "QtCore/qdebug.h"
|
||||
#include "QtCore/qpoint.h"
|
||||
+#include <QtCore/private/qnumeric_p.h>
|
||||
#include "QtCore/qsize.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@@ -182,6 +183,14 @@ Q_DECL_CONSTEXPR inline bool operator<(int i, const QFixed &f) { return i * 64 <
|
||||
Q_DECL_CONSTEXPR inline bool operator>(const QFixed &f, int i) { return f.value() > i * 64; }
|
||||
Q_DECL_CONSTEXPR inline bool operator>(int i, const QFixed &f) { return i * 64 > f.value(); }
|
||||
|
||||
+inline bool qAddOverflow(QFixed v1, QFixed v2, QFixed *r)
|
||||
+{
|
||||
+ int val;
|
||||
+ bool result = add_overflow(v1.value(), v2.value(), &val);
|
||||
+ r->setValue(val);
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
inline QDebug &operator<<(QDebug &dbg, const QFixed &f)
|
||||
{ return dbg << f.toReal(); }
|
||||
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
|
||||
index 26ac37b0..f6c69ff4 100644
|
||||
--- a/src/gui/text/qtextlayout.cpp
|
||||
+++ b/src/gui/text/qtextlayout.cpp
|
||||
@@ -2150,11 +2150,14 @@ found:
|
||||
eng->maxWidth = qMax(eng->maxWidth, line.textWidth);
|
||||
} else {
|
||||
eng->minWidth = qMax(eng->minWidth, lbh.minw);
|
||||
- eng->maxWidth += line.textWidth;
|
||||
+ if (qAddOverflow(eng->maxWidth, line.textWidth, &eng->maxWidth))
|
||||
+ eng->maxWidth = QFIXED_MAX;
|
||||
}
|
||||
|
||||
- if (line.textWidth > 0 && item < eng->layoutData->items.size())
|
||||
- eng->maxWidth += lbh.spaceData.textWidth;
|
||||
+ if (line.textWidth > 0 && item < eng->layoutData->items.size()) {
|
||||
+ if (qAddOverflow(eng->maxWidth, lbh.spaceData.textWidth, &eng->maxWidth))
|
||||
+ eng->maxWidth = QFIXED_MAX;
|
||||
+ }
|
||||
|
||||
line.textWidth += trailingSpace;
|
||||
if (lbh.spaceData.length) {
|
@ -1,97 +0,0 @@
|
||||
From 2103f2487f709dd9546c503820d9ad509e9a63b3 Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Macieira <thiago.macieira@intel.com>
|
||||
Date: Thu, 11 May 2023 21:40:15 -0700
|
||||
Subject: QDnsLookup/Unix: make sure we don't overflow the buffer
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The DNS Records are variable length and encode their size in 16 bits
|
||||
before the Record Data (RDATA). Ensure that both the RDATA and the
|
||||
Record header fields before it fall inside the buffer we have.
|
||||
|
||||
Additionally reject any replies containing more than one query records.
|
||||
|
||||
[ChangeLog][QtNetwork][QDnsLookup] Fixed a bug that could cause a buffer
|
||||
overflow in Unix systems while parsing corrupt, malicious, or truncated
|
||||
replies.
|
||||
|
||||
Pick-to: 5.15 6.2 6.5 6.5.1
|
||||
Change-Id: I3e3bfef633af4130a03afffd175e4b9547654b95
|
||||
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
|
||||
Reviewed-by: Jani Heikkinen <jani.heikkinen@qt.io>
|
||||
(cherry picked from commit 7dba2c87619d558a61a30eb30cc1d9c3fe6df94c)
|
||||
|
||||
* asturmlechner 2023-05-18: Resolve conflict with dev branch commit
|
||||
68b625901f9eb7c34e3d7aa302e1c0a454d3190b
|
||||
|
||||
diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp
|
||||
index 12b40fc35d..99e999d436 100644
|
||||
--- a/src/network/kernel/qdnslookup_unix.cpp
|
||||
+++ b/src/network/kernel/qdnslookup_unix.cpp
|
||||
@@ -227,7 +227,6 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
|
||||
// responseLength in case of error, we still can extract the
|
||||
// exact error code from the response.
|
||||
HEADER *header = (HEADER*)response;
|
||||
- const int answerCount = ntohs(header->ancount);
|
||||
switch (header->rcode) {
|
||||
case NOERROR:
|
||||
break;
|
||||
@@ -260,18 +259,31 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
|
||||
return;
|
||||
}
|
||||
|
||||
- // Skip the query host, type (2 bytes) and class (2 bytes).
|
||||
char host[PACKETSZ], answer[PACKETSZ];
|
||||
unsigned char *p = response + sizeof(HEADER);
|
||||
- int status = local_dn_expand(response, response + responseLength, p, host, sizeof(host));
|
||||
- if (status < 0) {
|
||||
+ int status;
|
||||
+
|
||||
+ if (ntohs(header->qdcount) == 1) {
|
||||
+ // Skip the query host, type (2 bytes) and class (2 bytes).
|
||||
+ status = local_dn_expand(response, response + responseLength, p, host, sizeof(host));
|
||||
+ if (status < 0) {
|
||||
+ reply->error = QDnsLookup::InvalidReplyError;
|
||||
+ reply->errorString = tr("Could not expand domain name");
|
||||
+ return;
|
||||
+ }
|
||||
+ if ((p - response) + status + 4 >= responseLength)
|
||||
+ header->qdcount = 0xffff; // invalid reply below
|
||||
+ else
|
||||
+ p += status + 4;
|
||||
+ }
|
||||
+ if (ntohs(header->qdcount) > 1) {
|
||||
reply->error = QDnsLookup::InvalidReplyError;
|
||||
- reply->errorString = tr("Could not expand domain name");
|
||||
+ reply->errorString = tr("Invalid reply received");
|
||||
return;
|
||||
}
|
||||
- p += status + 4;
|
||||
|
||||
// Extract results.
|
||||
+ const int answerCount = ntohs(header->ancount);
|
||||
int answerIndex = 0;
|
||||
while ((p < response + responseLength) && (answerIndex < answerCount)) {
|
||||
status = local_dn_expand(response, response + responseLength, p, host, sizeof(host));
|
||||
@@ -283,6 +295,11 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
|
||||
const QString name = QUrl::fromAce(host);
|
||||
|
||||
p += status;
|
||||
+
|
||||
+ if ((p - response) + 10 > responseLength) {
|
||||
+ // probably just a truncated reply, return what we have
|
||||
+ return;
|
||||
+ }
|
||||
const quint16 type = (p[0] << 8) | p[1];
|
||||
p += 2; // RR type
|
||||
p += 2; // RR class
|
||||
@@ -290,6 +307,8 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
|
||||
p += 4;
|
||||
const quint16 size = (p[0] << 8) | p[1];
|
||||
p += 2;
|
||||
+ if ((p - response) + size > responseLength)
|
||||
+ return; // truncated
|
||||
|
||||
if (type == QDnsLookup::A) {
|
||||
if (size != 4) {
|
@ -1,54 +0,0 @@
|
||||
--- a/src/network/ssl/qsslsocket_schannel.cpp
|
||||
+++ b/src/network/ssl/qsslsocket_schannel.cpp
|
||||
@@ -1880,6 +1880,28 @@ bool QSslSocketBackendPrivate::verifyCertContext(CERT_CONTEXT *certContext)
|
||||
if (configuration.peerVerifyDepth > 0 && DWORD(configuration.peerVerifyDepth) < verifyDepth)
|
||||
verifyDepth = DWORD(configuration.peerVerifyDepth);
|
||||
|
||||
+ const auto &caCertificates = q->sslConfiguration().caCertificates();
|
||||
+
|
||||
+ if (!rootCertOnDemandLoadingAllowed()
|
||||
+ && !(chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_PARTIAL_CHAIN)
|
||||
+ && (q->peerVerifyMode() == QSslSocket::VerifyPeer
|
||||
+ || (isClient && q->peerVerifyMode() == QSslSocket::AutoVerifyPeer))) {
|
||||
+ // When verifying a peer Windows "helpfully" builds a chain that
|
||||
+ // may include roots from the system store. But we don't want that if
|
||||
+ // the user has set their own CA certificates.
|
||||
+ // Since Windows claims this is not a partial chain the root is included
|
||||
+ // and we have to check that it is one of our configured CAs.
|
||||
+ CERT_CHAIN_ELEMENT *element = chain->rgpElement[chain->cElement - 1];
|
||||
+ QSslCertificate certificate = getCertificateFromChainElement(element);
|
||||
+ if (!caCertificates.contains(certificate)) {
|
||||
+ auto error = QSslError(QSslError::CertificateUntrusted, certificate);
|
||||
+ sslErrors += error;
|
||||
+ emit q->peerVerifyError(error);
|
||||
+ if (q->state() != QAbstractSocket::ConnectedState)
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
for (DWORD i = 0; i < verifyDepth; i++) {
|
||||
CERT_CHAIN_ELEMENT *element = chain->rgpElement[i];
|
||||
QSslCertificate certificate = getCertificateFromChainElement(element);
|
||||
|
||||
|
||||
--- a/src/network/ssl/qsslsocket.cpp
|
||||
+++ b/src/network/ssl/qsslsocket.cpp
|
||||
@@ -2221,6 +2221,10 @@ QSslSocketPrivate::QSslSocketPrivate()
|
||||
, flushTriggered(false)
|
||||
{
|
||||
QSslConfigurationPrivate::deepCopyDefaultConfiguration(&configuration);
|
||||
+ // If the global configuration doesn't allow root certificates to be loaded
|
||||
+ // on demand then we have to disable it for this socket as well.
|
||||
+ if (!configuration.allowRootCertOnDemandLoading)
|
||||
+ allowRootCertOnDemandLoading = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -2470,6 +2474,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
|
||||
ptr->sessionProtocol = global->sessionProtocol;
|
||||
ptr->ciphers = global->ciphers;
|
||||
ptr->caCertificates = global->caCertificates;
|
||||
+ ptr->allowRootCertOnDemandLoading = global->allowRootCertOnDemandLoading;
|
||||
ptr->protocol = global->protocol;
|
||||
ptr->peerVerifyMode = global->peerVerifyMode;
|
||||
ptr->peerVerifyDepth = global->peerVerifyDepth;
|
@ -1,203 +0,0 @@
|
||||
diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
|
||||
index 7cd457ba3a..11d162cb79 100644
|
||||
--- a/src/corelib/serialization/qxmlstream.cpp
|
||||
+++ b/src/corelib/serialization/qxmlstream.cpp
|
||||
@@ -1302,15 +1302,18 @@ inline int QXmlStreamReaderPrivate::fastScanContentCharList()
|
||||
return n;
|
||||
}
|
||||
|
||||
-inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
|
||||
+// Fast scan an XML attribute name (e.g. "xml:lang").
|
||||
+inline QXmlStreamReaderPrivate::FastScanNameResult
|
||||
+QXmlStreamReaderPrivate::fastScanName(Value *val)
|
||||
{
|
||||
int n = 0;
|
||||
uint c;
|
||||
while ((c = getChar()) != StreamEOF) {
|
||||
if (n >= 4096) {
|
||||
// This is too long to be a sensible name, and
|
||||
- // can exhaust memory
|
||||
- return 0;
|
||||
+ // can exhaust memory, or the range of decltype(*prefix)
|
||||
+ raiseNamePrefixTooLongError();
|
||||
+ return {};
|
||||
}
|
||||
switch (c) {
|
||||
case '\n':
|
||||
@@ -1339,23 +1342,23 @@ inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
|
||||
case '+':
|
||||
case '*':
|
||||
putChar(c);
|
||||
- if (prefix && *prefix == n+1) {
|
||||
- *prefix = 0;
|
||||
+ if (val && val->prefix == n + 1) {
|
||||
+ val->prefix = 0;
|
||||
putChar(':');
|
||||
--n;
|
||||
}
|
||||
- return n;
|
||||
+ return FastScanNameResult(n);
|
||||
case ':':
|
||||
- if (prefix) {
|
||||
- if (*prefix == 0) {
|
||||
- *prefix = n+2;
|
||||
+ if (val) {
|
||||
+ if (val->prefix == 0) {
|
||||
+ val->prefix = n + 2;
|
||||
} else { // only one colon allowed according to the namespace spec.
|
||||
putChar(c);
|
||||
- return n;
|
||||
+ return FastScanNameResult(n);
|
||||
}
|
||||
} else {
|
||||
putChar(c);
|
||||
- return n;
|
||||
+ return FastScanNameResult(n);
|
||||
}
|
||||
Q_FALLTHROUGH();
|
||||
default:
|
||||
@@ -1364,12 +1367,12 @@ inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
|
||||
}
|
||||
}
|
||||
|
||||
- if (prefix)
|
||||
- *prefix = 0;
|
||||
+ if (val)
|
||||
+ val->prefix = 0;
|
||||
int pos = textBuffer.size() - n;
|
||||
putString(textBuffer, pos);
|
||||
textBuffer.resize(pos);
|
||||
- return 0;
|
||||
+ return FastScanNameResult(0);
|
||||
}
|
||||
|
||||
enum NameChar { NameBeginning, NameNotBeginning, NotName };
|
||||
@@ -1878,6 +1881,14 @@ void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message)
|
||||
raiseError(QXmlStreamReader::NotWellFormedError, message);
|
||||
}
|
||||
|
||||
+void QXmlStreamReaderPrivate::raiseNamePrefixTooLongError()
|
||||
+{
|
||||
+ // TODO: add a ImplementationLimitsExceededError and use it instead
|
||||
+ raiseError(QXmlStreamReader::NotWellFormedError,
|
||||
+ QXmlStream::tr("Length of XML attribute name exceeds implemnetation limits (4KiB "
|
||||
+ "characters)."));
|
||||
+}
|
||||
+
|
||||
void QXmlStreamReaderPrivate::parseError()
|
||||
{
|
||||
|
||||
diff --git a/src/corelib/serialization/qxmlstream.g b/src/corelib/serialization/qxmlstream.g
|
||||
index 4321fed68a..8c6a1a5887 100644
|
||||
--- a/src/corelib/serialization/qxmlstream.g
|
||||
+++ b/src/corelib/serialization/qxmlstream.g
|
||||
@@ -516,7 +516,16 @@ public:
|
||||
int fastScanLiteralContent();
|
||||
int fastScanSpace();
|
||||
int fastScanContentCharList();
|
||||
- int fastScanName(int *prefix = nullptr);
|
||||
+
|
||||
+ struct FastScanNameResult {
|
||||
+ FastScanNameResult() : ok(false) {}
|
||||
+ explicit FastScanNameResult(int len) : addToLen(len), ok(true) { }
|
||||
+ operator bool() { return ok; }
|
||||
+ int operator*() { Q_ASSERT(ok); return addToLen; }
|
||||
+ int addToLen;
|
||||
+ bool ok;
|
||||
+ };
|
||||
+ FastScanNameResult fastScanName(Value *val = nullptr);
|
||||
inline int fastScanNMTOKEN();
|
||||
|
||||
|
||||
@@ -525,6 +534,7 @@ public:
|
||||
|
||||
void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
|
||||
void raiseWellFormedError(const QString &message);
|
||||
+ void raiseNamePrefixTooLongError();
|
||||
|
||||
QXmlStreamEntityResolver *entityResolver;
|
||||
|
||||
@@ -1811,7 +1821,12 @@ space_opt ::= space;
|
||||
qname ::= LETTER;
|
||||
/.
|
||||
case $rule_number: {
|
||||
- sym(1).len += fastScanName(&sym(1).prefix);
|
||||
+ Value &val = sym(1);
|
||||
+ if (auto res = fastScanName(&val))
|
||||
+ val.len += *res;
|
||||
+ else
|
||||
+ return false;
|
||||
+
|
||||
if (atEnd) {
|
||||
resume($rule_number);
|
||||
return false;
|
||||
@@ -1822,7 +1837,11 @@ qname ::= LETTER;
|
||||
name ::= LETTER;
|
||||
/.
|
||||
case $rule_number:
|
||||
- sym(1).len += fastScanName();
|
||||
+ if (auto res = fastScanName())
|
||||
+ sym(1).len += *res;
|
||||
+ else
|
||||
+ return false;
|
||||
+
|
||||
if (atEnd) {
|
||||
resume($rule_number);
|
||||
return false;
|
||||
diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h
|
||||
index e5bde7b98e..b01484cac3 100644
|
||||
--- a/src/corelib/serialization/qxmlstream_p.h
|
||||
+++ b/src/corelib/serialization/qxmlstream_p.h
|
||||
@@ -1005,7 +1005,16 @@ public:
|
||||
int fastScanLiteralContent();
|
||||
int fastScanSpace();
|
||||
int fastScanContentCharList();
|
||||
- int fastScanName(int *prefix = nullptr);
|
||||
+
|
||||
+ struct FastScanNameResult {
|
||||
+ FastScanNameResult() : ok(false) {}
|
||||
+ explicit FastScanNameResult(int len) : addToLen(len), ok(true) { }
|
||||
+ operator bool() { return ok; }
|
||||
+ int operator*() { Q_ASSERT(ok); return addToLen; }
|
||||
+ int addToLen;
|
||||
+ bool ok;
|
||||
+ };
|
||||
+ FastScanNameResult fastScanName(Value *val = nullptr);
|
||||
inline int fastScanNMTOKEN();
|
||||
|
||||
|
||||
@@ -1014,6 +1023,7 @@ public:
|
||||
|
||||
void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
|
||||
void raiseWellFormedError(const QString &message);
|
||||
+ void raiseNamePrefixTooLongError();
|
||||
|
||||
QXmlStreamEntityResolver *entityResolver;
|
||||
|
||||
@@ -1939,7 +1949,12 @@ bool QXmlStreamReaderPrivate::parse()
|
||||
break;
|
||||
|
||||
case 262: {
|
||||
- sym(1).len += fastScanName(&sym(1).prefix);
|
||||
+ Value &val = sym(1);
|
||||
+ if (auto res = fastScanName(&val))
|
||||
+ val.len += *res;
|
||||
+ else
|
||||
+ return false;
|
||||
+
|
||||
if (atEnd) {
|
||||
resume(262);
|
||||
return false;
|
||||
@@ -1947,7 +1962,11 @@ bool QXmlStreamReaderPrivate::parse()
|
||||
} break;
|
||||
|
||||
case 263:
|
||||
- sym(1).len += fastScanName();
|
||||
+ if (auto res = fastScanName())
|
||||
+ sym(1).len += *res;
|
||||
+ else
|
||||
+ return false;
|
||||
+
|
||||
if (atEnd) {
|
||||
resume(263);
|
||||
return false;
|
@ -1,219 +0,0 @@
|
||||
diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
|
||||
index bf8a2a9..6ab5d49 100644
|
||||
--- a/src/corelib/serialization/qxmlstream.cpp
|
||||
+++ b/src/corelib/serialization/qxmlstream.cpp
|
||||
@@ -160,7 +160,7 @@
|
||||
addData() or by waiting for it to arrive on the device().
|
||||
|
||||
\value UnexpectedElementError The parser encountered an element
|
||||
- that was different to those it expected.
|
||||
+ or token that was different to those it expected.
|
||||
|
||||
*/
|
||||
|
||||
@@ -295,13 +295,34 @@
|
||||
|
||||
QXmlStreamReader is a well-formed XML 1.0 parser that does \e not
|
||||
include external parsed entities. As long as no error occurs, the
|
||||
- application code can thus be assured that the data provided by the
|
||||
- stream reader satisfies the W3C's criteria for well-formed XML. For
|
||||
- example, you can be certain that all tags are indeed nested and
|
||||
- closed properly, that references to internal entities have been
|
||||
- replaced with the correct replacement text, and that attributes have
|
||||
- been normalized or added according to the internal subset of the
|
||||
- DTD.
|
||||
+ application code can thus be assured, that
|
||||
+ \list
|
||||
+ \li the data provided by the stream reader satisfies the W3C's
|
||||
+ criteria for well-formed XML,
|
||||
+ \li tokens are provided in a valid order.
|
||||
+ \endlist
|
||||
+
|
||||
+ Unless QXmlStreamReader raises an error, it guarantees the following:
|
||||
+ \list
|
||||
+ \li All tags are nested and closed properly.
|
||||
+ \li References to internal entities have been replaced with the
|
||||
+ correct replacement text.
|
||||
+ \li Attributes have been normalized or added according to the
|
||||
+ internal subset of the \l DTD.
|
||||
+ \li Tokens of type \l StartDocument happen before all others,
|
||||
+ aside from comments and processing instructions.
|
||||
+ \li At most one DOCTYPE element (a token of type \l DTD) is present.
|
||||
+ \li If present, the DOCTYPE appears before all other elements,
|
||||
+ aside from StartDocument, comments and processing instructions.
|
||||
+ \endlist
|
||||
+
|
||||
+ In particular, once any token of type \l StartElement, \l EndElement,
|
||||
+ \l Characters, \l EntityReference or \l EndDocument is seen, no
|
||||
+ tokens of type StartDocument or DTD will be seen. If one is present in
|
||||
+ the input stream, out of order, an error is raised.
|
||||
+
|
||||
+ \note The token types \l Comment and \l ProcessingInstruction may appear
|
||||
+ anywhere in the stream.
|
||||
|
||||
If an error occurs while parsing, atEnd() and hasError() return
|
||||
true, and error() returns the error that occurred. The functions
|
||||
@@ -620,6 +641,7 @@
|
||||
d->token = -1;
|
||||
return readNext();
|
||||
}
|
||||
+ d->checkToken();
|
||||
return d->type;
|
||||
}
|
||||
|
||||
@@ -740,6 +762,14 @@
|
||||
};
|
||||
|
||||
|
||||
+static const char QXmlStreamReader_XmlContextString[] =
|
||||
+ "Prolog\0"
|
||||
+ "Body\0";
|
||||
+
|
||||
+static const short QXmlStreamReader_XmlContextString_indices[] = {
|
||||
+ 0, 7
|
||||
+};
|
||||
+
|
||||
/*!
|
||||
\property QXmlStreamReader::namespaceProcessing
|
||||
The namespace-processing flag of the stream reader
|
||||
@@ -775,6 +805,16 @@
|
||||
QXmlStreamReader_tokenTypeString_indices[d->type]);
|
||||
}
|
||||
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \return \param ctxt (Prolog/Body) as a string.
|
||||
+ */
|
||||
+QString contextString(QXmlStreamReaderPrivate::XmlContext ctxt)
|
||||
+{
|
||||
+ return QLatin1String(QXmlStreamReader_XmlContextString +
|
||||
+ QXmlStreamReader_XmlContextString_indices[static_cast<int>(ctxt)]);
|
||||
+}
|
||||
+
|
||||
#endif // QT_NO_XMLSTREAMREADER
|
||||
|
||||
QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
|
||||
@@ -866,6 +906,8 @@
|
||||
|
||||
type = QXmlStreamReader::NoToken;
|
||||
error = QXmlStreamReader::NoError;
|
||||
+ currentContext = XmlContext::Prolog;
|
||||
+ foundDTD = false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4061,6 +4103,92 @@
|
||||
}
|
||||
}
|
||||
|
||||
+static bool isTokenAllowedInContext(QXmlStreamReader::TokenType type,
|
||||
+ QXmlStreamReaderPrivate::XmlContext loc)
|
||||
+{
|
||||
+ switch (type) {
|
||||
+ case QXmlStreamReader::StartDocument:
|
||||
+ case QXmlStreamReader::DTD:
|
||||
+ return loc == QXmlStreamReaderPrivate::XmlContext::Prolog;
|
||||
+
|
||||
+ case QXmlStreamReader::StartElement:
|
||||
+ case QXmlStreamReader::EndElement:
|
||||
+ case QXmlStreamReader::Characters:
|
||||
+ case QXmlStreamReader::EntityReference:
|
||||
+ case QXmlStreamReader::EndDocument:
|
||||
+ return loc == QXmlStreamReaderPrivate::XmlContext::Body;
|
||||
+
|
||||
+ case QXmlStreamReader::Comment:
|
||||
+ case QXmlStreamReader::ProcessingInstruction:
|
||||
+ return true;
|
||||
+
|
||||
+ case QXmlStreamReader::NoToken:
|
||||
+ case QXmlStreamReader::Invalid:
|
||||
+ return false;
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*!
|
||||
+ \internal
|
||||
+ \brief QXmlStreamReader::isValidToken
|
||||
+ \return \c true if \param type is a valid token type.
|
||||
+ \return \c false if \param type is an unexpected token,
|
||||
+ which indicates a non-well-formed or invalid XML stream.
|
||||
+ */
|
||||
+bool QXmlStreamReaderPrivate::isValidToken(QXmlStreamReader::TokenType type)
|
||||
+{
|
||||
+ // Don't change currentContext, if Invalid or NoToken occur in the prolog
|
||||
+ if (type == QXmlStreamReader::Invalid || type == QXmlStreamReader::NoToken)
|
||||
+ return false;
|
||||
+
|
||||
+ // If a token type gets rejected in the body, there is no recovery
|
||||
+ const bool result = isTokenAllowedInContext(type, currentContext);
|
||||
+ if (result || currentContext == XmlContext::Body)
|
||||
+ return result;
|
||||
+
|
||||
+ // First non-Prolog token observed => switch context to body and check again.
|
||||
+ currentContext = XmlContext::Body;
|
||||
+ return isTokenAllowedInContext(type, currentContext);
|
||||
+}
|
||||
+
|
||||
+/*!
|
||||
+ \internal
|
||||
+ Checks token type and raises an error, if it is invalid
|
||||
+ in the current context (prolog/body).
|
||||
+ */
|
||||
+void QXmlStreamReaderPrivate::checkToken()
|
||||
+{
|
||||
+ Q_Q(QXmlStreamReader);
|
||||
+
|
||||
+ // The token type must be consumed, to keep track if the body has been reached.
|
||||
+ const XmlContext context = currentContext;
|
||||
+ const bool ok = isValidToken(type);
|
||||
+
|
||||
+ // Do nothing if an error has been raised already (going along with an unexpected token)
|
||||
+ if (error != QXmlStreamReader::Error::NoError)
|
||||
+ return;
|
||||
+
|
||||
+ if (!ok) {
|
||||
+ raiseError(QXmlStreamReader::UnexpectedElementError,
|
||||
+ QLatin1String("Unexpected token type %1 in %2.")
|
||||
+ .arg(q->tokenString(), contextString(context)));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (type != QXmlStreamReader::DTD)
|
||||
+ return;
|
||||
+
|
||||
+ // Raise error on multiple DTD tokens
|
||||
+ if (foundDTD) {
|
||||
+ raiseError(QXmlStreamReader::UnexpectedElementError,
|
||||
+ QLatin1String("Found second DTD token in %1.").arg(contextString(context)));
|
||||
+ } else {
|
||||
+ foundDTD = true;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/*!
|
||||
\fn bool QXmlStreamAttributes::hasAttribute(const QString &qualifiedName) const
|
||||
\since 4.5
|
||||
diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h
|
||||
index 8f7c9e0..708059b 100644
|
||||
--- a/src/corelib/serialization/qxmlstream_p.h
|
||||
+++ b/src/corelib/serialization/qxmlstream_p.h
|
||||
@@ -804,6 +804,17 @@
|
||||
#endif
|
||||
bool atEnd;
|
||||
|
||||
+ enum class XmlContext
|
||||
+ {
|
||||
+ Prolog,
|
||||
+ Body,
|
||||
+ };
|
||||
+
|
||||
+ XmlContext currentContext = XmlContext::Prolog;
|
||||
+ bool foundDTD = false;
|
||||
+ bool isValidToken(QXmlStreamReader::TokenType type);
|
||||
+ void checkToken();
|
||||
+
|
||||
/*!
|
||||
\sa setType()
|
||||
*/
|
@ -1,197 +0,0 @@
|
||||
diff --git a/src/gui/util/qktxhandler.cpp b/src/gui/util/qktxhandler.cpp
|
||||
index 0d98e97453..6a79e55109 100644
|
||||
--- a/src/gui/util/qktxhandler.cpp
|
||||
+++ b/src/gui/util/qktxhandler.cpp
|
||||
@@ -73,7 +73,7 @@ struct KTXHeader {
|
||||
quint32 bytesOfKeyValueData;
|
||||
};
|
||||
|
||||
-static const quint32 headerSize = sizeof(KTXHeader);
|
||||
+static constexpr quint32 qktxh_headerSize = sizeof(KTXHeader);
|
||||
|
||||
// Currently unused, declared for future reference
|
||||
struct KTXKeyValuePairItem {
|
||||
@@ -103,11 +103,36 @@ struct KTXMipmapLevel {
|
||||
*/
|
||||
};
|
||||
|
||||
-bool QKtxHandler::canRead(const QByteArray &suffix, const QByteArray &block)
|
||||
+static bool qAddOverflow(quint32 v1, quint32 v2, quint32 *r) {
|
||||
+ // unsigned additions are well-defined
|
||||
+ *r = v1 + v2;
|
||||
+ return v1 > quint32(v1 + v2);
|
||||
+}
|
||||
+
|
||||
+// Returns the nearest multiple of 4 greater than or equal to 'value'
|
||||
+static bool nearestMultipleOf4(quint32 value, quint32 *result)
|
||||
+{
|
||||
+ constexpr quint32 rounding = 4;
|
||||
+ *result = 0;
|
||||
+ if (qAddOverflow(value, rounding - 1, result))
|
||||
+ return true;
|
||||
+ *result &= ~(rounding - 1);
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+// Returns a slice with prechecked bounds
|
||||
+static QByteArray safeSlice(const QByteArray& array, quint32 start, quint32 length)
|
||||
{
|
||||
- Q_UNUSED(suffix)
|
||||
+ quint32 end = 0;
|
||||
+ if (qAddOverflow(start, length, &end) || end > quint32(array.length()))
|
||||
+ return {};
|
||||
+ return QByteArray(array.data() + start, length);
|
||||
+}
|
||||
|
||||
- return (qstrncmp(block.constData(), ktxIdentifier, KTX_IDENTIFIER_LENGTH) == 0);
|
||||
+bool QKtxHandler::canRead(const QByteArray &suffix, const QByteArray &block)
|
||||
+{
|
||||
+ Q_UNUSED(suffix);
|
||||
+ return block.startsWith(QByteArray::fromRawData(ktxIdentifier, KTX_IDENTIFIER_LENGTH));
|
||||
}
|
||||
|
||||
QTextureFileData QKtxHandler::read()
|
||||
@@ -115,42 +140,97 @@ QTextureFileData QKtxHandler::read()
|
||||
if (!device())
|
||||
return QTextureFileData();
|
||||
|
||||
- QByteArray buf = device()->readAll();
|
||||
- const quint32 dataSize = quint32(buf.size());
|
||||
- if (dataSize < headerSize || !canRead(QByteArray(), buf)) {
|
||||
- qCDebug(lcQtGuiTextureIO, "Invalid KTX file %s", logName().constData());
|
||||
+ const QByteArray buf = device()->readAll();
|
||||
+ if (size_t(buf.size()) > std::numeric_limits<quint32>::max()) {
|
||||
+ qWarning(lcQtGuiTextureIO, "Too big KTX file %s", logName().constData());
|
||||
+ return QTextureFileData();
|
||||
+ }
|
||||
+
|
||||
+ if (!canRead(QByteArray(), buf)) {
|
||||
+ qWarning(lcQtGuiTextureIO, "Invalid KTX file %s", logName().constData());
|
||||
+ return QTextureFileData();
|
||||
+ }
|
||||
+
|
||||
+ if (buf.size() < qsizetype(qktxh_headerSize)) {
|
||||
+ qWarning(lcQtGuiTextureIO, "Invalid KTX header size in %s", logName().constData());
|
||||
return QTextureFileData();
|
||||
}
|
||||
|
||||
- const KTXHeader *header = reinterpret_cast<const KTXHeader *>(buf.constData());
|
||||
- if (!checkHeader(*header)) {
|
||||
- qCDebug(lcQtGuiTextureIO, "Unsupported KTX file format in %s", logName().constData());
|
||||
+ KTXHeader header;
|
||||
+ memcpy(&header, buf.data(), qktxh_headerSize);
|
||||
+ if (!checkHeader(header)) {
|
||||
+ qWarning(lcQtGuiTextureIO, "Unsupported KTX file format in %s", logName().constData());
|
||||
return QTextureFileData();
|
||||
}
|
||||
|
||||
QTextureFileData texData;
|
||||
texData.setData(buf);
|
||||
|
||||
- texData.setSize(QSize(decode(header->pixelWidth), decode(header->pixelHeight)));
|
||||
- texData.setGLFormat(decode(header->glFormat));
|
||||
- texData.setGLInternalFormat(decode(header->glInternalFormat));
|
||||
- texData.setGLBaseInternalFormat(decode(header->glBaseInternalFormat));
|
||||
-
|
||||
- texData.setNumLevels(decode(header->numberOfMipmapLevels));
|
||||
- quint32 offset = headerSize + decode(header->bytesOfKeyValueData);
|
||||
- const int maxLevels = qMin(texData.numLevels(), 32); // Cap iterations in case of corrupt file.
|
||||
- for (int i = 0; i < maxLevels; i++) {
|
||||
- if (offset + sizeof(KTXMipmapLevel) > dataSize) // Corrupt file; avoid oob read
|
||||
- break;
|
||||
- const KTXMipmapLevel *level = reinterpret_cast<const KTXMipmapLevel *>(buf.constData() + offset);
|
||||
- quint32 levelLen = decode(level->imageSize);
|
||||
- texData.setDataOffset(offset + sizeof(KTXMipmapLevel::imageSize), i);
|
||||
- texData.setDataLength(levelLen, i);
|
||||
- offset += sizeof(KTXMipmapLevel::imageSize) + levelLen + (3 - ((levelLen + 3) % 4));
|
||||
+ texData.setSize(QSize(decode(header.pixelWidth), decode(header.pixelHeight)));
|
||||
+ texData.setGLFormat(decode(header.glFormat));
|
||||
+ texData.setGLInternalFormat(decode(header.glInternalFormat));
|
||||
+ texData.setGLBaseInternalFormat(decode(header.glBaseInternalFormat));
|
||||
+
|
||||
+ texData.setNumLevels(decode(header.numberOfMipmapLevels));
|
||||
+
|
||||
+ const quint32 bytesOfKeyValueData = decode(header.bytesOfKeyValueData);
|
||||
+ quint32 headerKeyValueSize;
|
||||
+ if (qAddOverflow(qktxh_headerSize, bytesOfKeyValueData, &headerKeyValueSize)) {
|
||||
+ qWarning(lcQtGuiTextureIO, "Overflow in size of key value data in header of KTX file %s",
|
||||
+ logName().constData());
|
||||
+ return QTextureFileData();
|
||||
+ }
|
||||
+
|
||||
+ if (headerKeyValueSize >= quint32(buf.size())) {
|
||||
+ qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", logName().constData());
|
||||
+ return QTextureFileData();
|
||||
+ }
|
||||
+
|
||||
+ // Technically, any number of levels is allowed but if the value is bigger than
|
||||
+ // what is possible in KTX V2 (and what makes sense) we return an error.
|
||||
+ // maxLevels = log2(max(width, height, depth))
|
||||
+ const int maxLevels = (sizeof(quint32) * 8)
|
||||
+ - qCountLeadingZeroBits(std::max(
|
||||
+ { header.pixelWidth, header.pixelHeight, header.pixelDepth }));
|
||||
+
|
||||
+ if (texData.numLevels() > maxLevels) {
|
||||
+ qWarning(lcQtGuiTextureIO, "Too many levels in KTX file %s", logName().constData());
|
||||
+ return QTextureFileData();
|
||||
+ }
|
||||
+
|
||||
+ quint32 offset = headerKeyValueSize;
|
||||
+ for (int level = 0; level < texData.numLevels(); level++) {
|
||||
+ const auto imageSizeSlice = safeSlice(buf, offset, sizeof(quint32));
|
||||
+ if (imageSizeSlice.isEmpty()) {
|
||||
+ qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", logName().constData());
|
||||
+ return QTextureFileData();
|
||||
+ }
|
||||
+
|
||||
+ const quint32 imageSize = decode(qFromUnaligned<quint32>(imageSizeSlice.data()));
|
||||
+ offset += sizeof(quint32); // overflow checked indirectly above
|
||||
+
|
||||
+ texData.setDataOffset(offset, level);
|
||||
+ texData.setDataLength(imageSize, level);
|
||||
+
|
||||
+ // Add image data and padding to offset
|
||||
+ quint32 padded = 0;
|
||||
+ if (nearestMultipleOf4(imageSize, &padded)) {
|
||||
+ qWarning(lcQtGuiTextureIO, "Overflow in KTX file %s", logName().constData());
|
||||
+ return QTextureFileData();
|
||||
+ }
|
||||
+
|
||||
+ quint32 offsetNext;
|
||||
+ if (qAddOverflow(offset, padded, &offsetNext)) {
|
||||
+ qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", logName().constData());
|
||||
+ return QTextureFileData();
|
||||
+ }
|
||||
+
|
||||
+ offset = offsetNext;
|
||||
}
|
||||
|
||||
if (!texData.isValid()) {
|
||||
- qCDebug(lcQtGuiTextureIO, "Invalid values in header of KTX file %s", logName().constData());
|
||||
+ qWarning(lcQtGuiTextureIO, "Invalid values in header of KTX file %s",
|
||||
+ logName().constData());
|
||||
return QTextureFileData();
|
||||
}
|
||||
|
||||
@@ -191,7 +271,7 @@ bool QKtxHandler::checkHeader(const KTXHeader &header)
|
||||
(decode(header.numberOfFaces) == 1));
|
||||
}
|
||||
|
||||
-quint32 QKtxHandler::decode(quint32 val)
|
||||
+quint32 QKtxHandler::decode(quint32 val) const
|
||||
{
|
||||
return inverseEndian ? qbswap<quint32>(val) : val;
|
||||
}
|
||||
diff --git a/src/gui/util/qktxhandler_p.h b/src/gui/util/qktxhandler_p.h
|
||||
index f831e59d95..cdf1b2eaf8 100644
|
||||
--- a/src/gui/util/qktxhandler_p.h
|
||||
+++ b/src/gui/util/qktxhandler_p.h
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
|
||||
private:
|
||||
bool checkHeader(const KTXHeader &header);
|
||||
- quint32 decode(quint32 val);
|
||||
+ quint32 decode(quint32 val) const;
|
||||
|
||||
bool inverseEndian = false;
|
||||
};
|
@ -1,232 +0,0 @@
|
||||
From b1e75376cc3adfc7da5502a277dfe9711f3e0536 Mon Sep 17 00:00:00 2001
|
||||
From: Mårten Nordheim <marten.nordheim@qt.io>
|
||||
Date: Tue, 25 Jun 2024 17:09:35 +0200
|
||||
Subject: [PATCH] HTTP2: Delay any communication until encrypted() can be responded to
|
||||
|
||||
We have the encrypted() signal that lets users do extra checks on the
|
||||
established connection. It is emitted as BlockingQueued, so the HTTP
|
||||
thread stalls until it is done emitting. Users can potentially call
|
||||
abort() on the QNetworkReply at that point, which is passed as a Queued
|
||||
call back to the HTTP thread. That means that any currently queued
|
||||
signal emission will be processed before the abort() call is processed.
|
||||
|
||||
In the case of HTTP2 it is a little special since it is multiplexed and
|
||||
the code is built to start requests as they are available. This means
|
||||
that, while the code worked fine for HTTP1, since one connection only
|
||||
has one request, it is not working for HTTP2, since we try to send more
|
||||
requests in-between the encrypted() signal and the abort() call.
|
||||
|
||||
This patch changes the code to delay any communication until the
|
||||
encrypted() signal has been emitted and processed, for HTTP2 only.
|
||||
It's done by adding a few booleans, both to know that we have to return
|
||||
early and so we can keep track of what events arose and what we need to
|
||||
resume once enough time has passed that any abort() call must have been
|
||||
processed.
|
||||
|
||||
Fixes: QTBUG-126610
|
||||
Pick-to: 6.8 6.7 6.5 6.2 5.15 5.12
|
||||
Change-Id: Ic25a600c278203256e35f541026f34a8783235ae
|
||||
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
|
||||
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
|
||||
---
|
||||
|
||||
diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp
|
||||
index 39dd4608..bc1dac68 100644
|
||||
--- a/src/network/access/qhttp2protocolhandler.cpp
|
||||
+++ b/src/network/access/qhttp2protocolhandler.cpp
|
||||
@@ -371,12 +371,12 @@ bool QHttp2ProtocolHandler::sendRequest()
|
||||
}
|
||||
}
|
||||
|
||||
- if (!prefaceSent && !sendClientPreface())
|
||||
- return false;
|
||||
-
|
||||
if (!requests.size())
|
||||
return true;
|
||||
|
||||
+ if (!prefaceSent && !sendClientPreface())
|
||||
+ return false;
|
||||
+
|
||||
m_channel->state = QHttpNetworkConnectionChannel::WritingState;
|
||||
// Check what was promised/pushed, maybe we do not have to send a request
|
||||
// and have a response already?
|
||||
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
|
||||
index 7620ca16..e15b0810 100644
|
||||
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
|
||||
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
|
||||
@@ -255,6 +255,10 @@ void QHttpNetworkConnectionChannel::abort()
|
||||
bool QHttpNetworkConnectionChannel::sendRequest()
|
||||
{
|
||||
Q_ASSERT(!protocolHandler.isNull());
|
||||
+ if (waitingForPotentialAbort) {
|
||||
+ needInvokeSendRequest = true;
|
||||
+ return false; // this return value is unused
|
||||
+ }
|
||||
return protocolHandler->sendRequest();
|
||||
}
|
||||
|
||||
@@ -267,21 +271,28 @@ bool QHttpNetworkConnectionChannel::sendRequest()
|
||||
void QHttpNetworkConnectionChannel::sendRequestDelayed()
|
||||
{
|
||||
QMetaObject::invokeMethod(this, [this] {
|
||||
- Q_ASSERT(!protocolHandler.isNull());
|
||||
if (reply)
|
||||
- protocolHandler->sendRequest();
|
||||
+ sendRequest();
|
||||
}, Qt::ConnectionType::QueuedConnection);
|
||||
}
|
||||
|
||||
void QHttpNetworkConnectionChannel::_q_receiveReply()
|
||||
{
|
||||
Q_ASSERT(!protocolHandler.isNull());
|
||||
+ if (waitingForPotentialAbort) {
|
||||
+ needInvokeReceiveReply = true;
|
||||
+ return;
|
||||
+ }
|
||||
protocolHandler->_q_receiveReply();
|
||||
}
|
||||
|
||||
void QHttpNetworkConnectionChannel::_q_readyRead()
|
||||
{
|
||||
Q_ASSERT(!protocolHandler.isNull());
|
||||
+ if (waitingForPotentialAbort) {
|
||||
+ needInvokeReadyRead = true;
|
||||
+ return;
|
||||
+ }
|
||||
protocolHandler->_q_readyRead();
|
||||
}
|
||||
|
||||
@@ -1289,7 +1300,18 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
|
||||
// Similar to HTTP/1.1 counterpart below:
|
||||
const auto &pairs = spdyRequestsToSend.values(); // (request, reply)
|
||||
const auto &pair = pairs.first();
|
||||
+ waitingForPotentialAbort = true;
|
||||
emit pair.second->encrypted();
|
||||
+
|
||||
+ // We don't send or handle any received data until any effects from
|
||||
+ // emitting encrypted() have been processed. This is necessary
|
||||
+ // because the user may have called abort(). We may also abort the
|
||||
+ // whole connection if the request has been aborted and there is
|
||||
+ // no more requests to send.
|
||||
+ QMetaObject::invokeMethod(this,
|
||||
+ &QHttpNetworkConnectionChannel::checkAndResumeCommunication,
|
||||
+ Qt::QueuedConnection);
|
||||
+
|
||||
// In case our peer has sent us its settings (window size, max concurrent streams etc.)
|
||||
// let's give _q_receiveReply a chance to read them first ('invokeMethod', QueuedConnection).
|
||||
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
|
||||
@@ -1307,6 +1329,28 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
|
||||
}
|
||||
}
|
||||
|
||||
+void QHttpNetworkConnectionChannel::checkAndResumeCommunication()
|
||||
+{
|
||||
+ Q_ASSERT(connection->connectionType() == QHttpNetworkConnection::ConnectionTypeSPDY
|
||||
+ || connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2
|
||||
+ || connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct);
|
||||
+
|
||||
+ // Because HTTP/2 requires that we send a SETTINGS frame as the first thing we do, and respond
|
||||
+ // to a SETTINGS frame with an ACK, we need to delay any handling until we can ensure that any
|
||||
+ // effects from emitting encrypted() have been processed.
|
||||
+ // This function is called after encrypted() was emitted, so check for changes.
|
||||
+
|
||||
+ if (!reply && spdyRequestsToSend.isEmpty())
|
||||
+ abort();
|
||||
+ waitingForPotentialAbort = false;
|
||||
+ if (needInvokeReadyRead)
|
||||
+ _q_readyRead();
|
||||
+ if (needInvokeReceiveReply)
|
||||
+ _q_receiveReply();
|
||||
+ if (needInvokeSendRequest)
|
||||
+ sendRequest();
|
||||
+}
|
||||
+
|
||||
void QHttpNetworkConnectionChannel::requeueSpdyRequests()
|
||||
{
|
||||
QList<HttpMessagePair> spdyPairs = spdyRequestsToSend.values();
|
||||
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
|
||||
index d8ac3979..eac44464 100644
|
||||
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
|
||||
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
|
||||
@@ -107,6 +107,10 @@ public:
|
||||
QAbstractSocket *socket;
|
||||
bool ssl;
|
||||
bool isInitialized;
|
||||
+ bool waitingForPotentialAbort = false;
|
||||
+ bool needInvokeReceiveReply = false;
|
||||
+ bool needInvokeReadyRead = false;
|
||||
+ bool needInvokeSendRequest = false;
|
||||
ChannelState state;
|
||||
QHttpNetworkRequest request; // current request, only used for HTTP
|
||||
QHttpNetworkReply *reply; // current reply for this request, only used for HTTP
|
||||
@@ -187,6 +191,8 @@ public:
|
||||
void closeAndResendCurrentRequest();
|
||||
void resendCurrentRequest();
|
||||
|
||||
+ void checkAndResumeCommunication();
|
||||
+
|
||||
bool isSocketBusy() const;
|
||||
bool isSocketWriting() const;
|
||||
bool isSocketWaiting() const;
|
||||
diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp
|
||||
index bf8c7799..8ed95b99 100644
|
||||
--- a/tests/auto/network/access/http2/tst_http2.cpp
|
||||
+++ b/tests/auto/network/access/http2/tst_http2.cpp
|
||||
@@ -118,6 +118,8 @@ private slots:
|
||||
void redirect_data();
|
||||
void redirect();
|
||||
|
||||
+ void abortOnEncrypted();
|
||||
+
|
||||
protected slots:
|
||||
// Slots to listen to our in-process server:
|
||||
void serverStarted(quint16 port);
|
||||
@@ -1024,6 +1026,48 @@ void tst_Http2::redirect()
|
||||
QTRY_VERIFY(serverGotSettingsACK);
|
||||
}
|
||||
|
||||
+void tst_Http2::abortOnEncrypted()
|
||||
+{
|
||||
+#if !QT_CONFIG(ssl)
|
||||
+ QSKIP("TLS support is needed for this test");
|
||||
+#else
|
||||
+ clearHTTP2State();
|
||||
+ serverPort = 0;
|
||||
+
|
||||
+ ServerPtr targetServer(newServer(defaultServerSettings, H2Type::h2Direct));
|
||||
+
|
||||
+ QMetaObject::invokeMethod(targetServer.data(), "startServer", Qt::QueuedConnection);
|
||||
+ runEventLoop();
|
||||
+
|
||||
+ nRequests = 1;
|
||||
+ nSentRequests = 0;
|
||||
+
|
||||
+ const auto url = requestUrl(H2Type::h2Direct);
|
||||
+ QNetworkRequest request(url);
|
||||
+ request.setAttribute(QNetworkRequest::Http2DirectAttribute, true);
|
||||
+
|
||||
+ std::unique_ptr<QNetworkReply> reply{manager->get(request)};
|
||||
+ reply->ignoreSslErrors();
|
||||
+ connect(reply.get(), &QNetworkReply::encrypted, reply.get(), [reply = reply.get()](){
|
||||
+ reply->abort();
|
||||
+ });
|
||||
+ connect(reply.get(), &QNetworkReply::errorOccurred, this, &tst_Http2::replyFinishedWithError);
|
||||
+
|
||||
+ runEventLoop();
|
||||
+ STOP_ON_FAILURE
|
||||
+
|
||||
+ QCOMPARE(nRequests, 0);
|
||||
+ QCOMPARE(reply->error(), QNetworkReply::OperationCanceledError);
|
||||
+
|
||||
+ const bool res = QTest::qWaitFor(
|
||||
+ [this, server = targetServer.get()]() {
|
||||
+ return serverGotSettingsACK || prefaceOK || nSentRequests > 0;
|
||||
+ },
|
||||
+ 500);
|
||||
+ QVERIFY(!res);
|
||||
+#endif // QT_CONFIG(ssl)
|
||||
+}
|
||||
+
|
||||
void tst_Http2::serverStarted(quint16 port)
|
||||
{
|
||||
serverPort = port;
|
@ -0,0 +1,136 @@
|
||||
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
|
||||
index 4aba9ff..439e51a 100644
|
||||
--- a/src/gui/kernel/qevent.h
|
||||
+++ b/src/gui/kernel/qevent.h
|
||||
@@ -104,15 +104,15 @@ protected:
|
||||
class Q_GUI_EXPORT QMouseEvent : public QInputEvent
|
||||
{
|
||||
public:
|
||||
- QMouseEvent(Type type, const QPointF &localPos, Qt::MouseButton button,
|
||||
+ QMouseEvent(QEvent::Type type, const QPointF &localPos, Qt::MouseButton button,
|
||||
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
|
||||
- QMouseEvent(Type type, const QPointF &localPos, const QPointF &screenPos,
|
||||
+ QMouseEvent(QEvent::Type type, const QPointF &localPos, const QPointF &screenPos,
|
||||
Qt::MouseButton button, Qt::MouseButtons buttons,
|
||||
Qt::KeyboardModifiers modifiers);
|
||||
- QMouseEvent(Type type, const QPointF &localPos, const QPointF &windowPos, const QPointF &screenPos,
|
||||
+ QMouseEvent(QEvent::Type type, const QPointF &localPos, const QPointF &windowPos, const QPointF &screenPos,
|
||||
Qt::MouseButton button, Qt::MouseButtons buttons,
|
||||
Qt::KeyboardModifiers modifiers);
|
||||
- QMouseEvent(Type type, const QPointF &localPos, const QPointF &windowPos, const QPointF &screenPos,
|
||||
+ QMouseEvent(QEvent::Type type, const QPointF &localPos, const QPointF &windowPos, const QPointF &screenPos,
|
||||
Qt::MouseButton button, Qt::MouseButtons buttons,
|
||||
Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source);
|
||||
~QMouseEvent();
|
||||
@@ -154,7 +154,7 @@ protected:
|
||||
class Q_GUI_EXPORT QHoverEvent : public QInputEvent
|
||||
{
|
||||
public:
|
||||
- QHoverEvent(Type type, const QPointF &pos, const QPointF &oldPos, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
|
||||
+ QHoverEvent(QEvent::Type type, const QPointF &pos, const QPointF &oldPos, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
|
||||
~QHoverEvent();
|
||||
|
||||
#ifndef QT_NO_INTEGER_EVENT_COORDINATES
|
||||
@@ -282,12 +282,12 @@ public:
|
||||
#if QT_DEPRECATED_SINCE(5, 15)
|
||||
// Actually deprecated since 5.4, in docs
|
||||
QT_DEPRECATED_VERSION_X_5_15("Use the other QTabletEvent constructor")
|
||||
- QTabletEvent(Type t, const QPointF &pos, const QPointF &globalPos,
|
||||
+ QTabletEvent(QEvent::Type t, const QPointF &pos, const QPointF &globalPos,
|
||||
int device, int pointerType, qreal pressure, int xTilt, int yTilt,
|
||||
qreal tangentialPressure, qreal rotation, int z,
|
||||
Qt::KeyboardModifiers keyState, qint64 uniqueID); // ### remove in Qt 6
|
||||
#endif
|
||||
- QTabletEvent(Type t, const QPointF &pos, const QPointF &globalPos,
|
||||
+ QTabletEvent(QEvent::Type t, const QPointF &pos, const QPointF &globalPos,
|
||||
int device, int pointerType, qreal pressure, int xTilt, int yTilt,
|
||||
qreal tangentialPressure, qreal rotation, int z,
|
||||
Qt::KeyboardModifiers keyState, qint64 uniqueID,
|
||||
@@ -377,9 +377,9 @@ protected:
|
||||
class Q_GUI_EXPORT QKeyEvent : public QInputEvent
|
||||
{
|
||||
public:
|
||||
- QKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers, const QString& text = QString(),
|
||||
+ QKeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, const QString& text = QString(),
|
||||
bool autorep = false, ushort count = 1);
|
||||
- QKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers,
|
||||
+ QKeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
|
||||
quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers,
|
||||
const QString &text = QString(), bool autorep = false, ushort count = 1);
|
||||
~QKeyEvent();
|
||||
@@ -399,7 +399,7 @@ public:
|
||||
|
||||
// Functions for the extended key event information
|
||||
#if QT_DEPRECATED_SINCE(5, 0)
|
||||
- static inline QKeyEvent *createExtendedKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers,
|
||||
+ static inline QKeyEvent *createExtendedKeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
|
||||
quint32 nativeScanCode, quint32 nativeVirtualKey,
|
||||
quint32 nativeModifiers,
|
||||
const QString& text = QString(), bool autorep = false,
|
||||
@@ -682,7 +682,7 @@ class Q_GUI_EXPORT QDragMoveEvent : public QDropEvent
|
||||
{
|
||||
public:
|
||||
QDragMoveEvent(const QPoint &pos, Qt::DropActions actions, const QMimeData *data,
|
||||
- Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Type type = DragMove);
|
||||
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, QEvent::Type type = QEvent::DragMove);
|
||||
~QDragMoveEvent();
|
||||
|
||||
inline QRect answerRect() const { return rect; }
|
||||
diff --git a/src/widgets/graphicsview/qgraphicssceneevent.h b/src/widgets/graphicsview/qgraphicssceneevent.h
|
||||
index 9d940be..b7dc19b 100644
|
||||
--- a/src/widgets/graphicsview/qgraphicssceneevent.h
|
||||
+++ b/src/widgets/graphicsview/qgraphicssceneevent.h
|
||||
@@ -82,7 +82,7 @@ class QGraphicsSceneMouseEventPrivate;
|
||||
class Q_WIDGETS_EXPORT QGraphicsSceneMouseEvent : public QGraphicsSceneEvent
|
||||
{
|
||||
public:
|
||||
- explicit QGraphicsSceneMouseEvent(Type type = None);
|
||||
+ explicit QGraphicsSceneMouseEvent(QEvent::Type type = QEvent::None);
|
||||
~QGraphicsSceneMouseEvent();
|
||||
|
||||
QPointF pos() const;
|
||||
@@ -136,7 +136,7 @@ class QGraphicsSceneWheelEventPrivate;
|
||||
class Q_WIDGETS_EXPORT QGraphicsSceneWheelEvent : public QGraphicsSceneEvent
|
||||
{
|
||||
public:
|
||||
- explicit QGraphicsSceneWheelEvent(Type type = None);
|
||||
+ explicit QGraphicsSceneWheelEvent(QEvent::Type type = QEvent::None);
|
||||
~QGraphicsSceneWheelEvent();
|
||||
|
||||
QPointF pos() const;
|
||||
@@ -171,7 +171,7 @@ class Q_WIDGETS_EXPORT QGraphicsSceneContextMenuEvent : public QGraphicsSceneEve
|
||||
public:
|
||||
enum Reason { Mouse, Keyboard, Other };
|
||||
|
||||
- explicit QGraphicsSceneContextMenuEvent(Type type = None);
|
||||
+ explicit QGraphicsSceneContextMenuEvent(QEvent::Type type = QEvent::None);
|
||||
~QGraphicsSceneContextMenuEvent();
|
||||
|
||||
QPointF pos() const;
|
||||
@@ -198,7 +198,7 @@ class QGraphicsSceneHoverEventPrivate;
|
||||
class Q_WIDGETS_EXPORT QGraphicsSceneHoverEvent : public QGraphicsSceneEvent
|
||||
{
|
||||
public:
|
||||
- explicit QGraphicsSceneHoverEvent(Type type = None);
|
||||
+ explicit QGraphicsSceneHoverEvent(QEvent::Type type = QEvent::None);
|
||||
~QGraphicsSceneHoverEvent();
|
||||
|
||||
QPointF pos() const;
|
||||
@@ -231,7 +231,7 @@ class QGraphicsSceneHelpEventPrivate;
|
||||
class Q_WIDGETS_EXPORT QGraphicsSceneHelpEvent : public QGraphicsSceneEvent
|
||||
{
|
||||
public:
|
||||
- explicit QGraphicsSceneHelpEvent(Type type = None);
|
||||
+ explicit QGraphicsSceneHelpEvent(QEvent::Type type = QEvent::None);
|
||||
~QGraphicsSceneHelpEvent();
|
||||
|
||||
QPointF scenePos() const;
|
||||
@@ -249,7 +249,7 @@ class QGraphicsSceneDragDropEventPrivate;
|
||||
class Q_WIDGETS_EXPORT QGraphicsSceneDragDropEvent : public QGraphicsSceneEvent
|
||||
{
|
||||
public:
|
||||
- explicit QGraphicsSceneDragDropEvent(Type type = None);
|
||||
+ explicit QGraphicsSceneDragDropEvent(QEvent::Type type = QEvent::None);
|
||||
~QGraphicsSceneDragDropEvent();
|
||||
|
||||
QPointF pos() const;
|
@ -0,0 +1,12 @@
|
||||
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
|
||||
index 00aa80cd..dd715b73 100644
|
||||
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
|
||||
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
|
||||
@@ -564,6 +564,7 @@ void QFontconfigDatabase::populateFontDatabase()
|
||||
FcObjectSetAdd(os, *p);
|
||||
++p;
|
||||
}
|
||||
+ FcPatternAddBool(pattern, FC_VARIABLE, FcFalse);
|
||||
fonts = FcFontList(nullptr, pattern, os);
|
||||
FcObjectSetDestroy(os);
|
||||
FcPatternDestroy(pattern);
|
@ -0,0 +1,108 @@
|
||||
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
|
||||
index 159b490c..110f2dcf 100644
|
||||
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
|
||||
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
|
||||
@@ -951,6 +951,7 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef
|
||||
QFontEngine::GlyphFormat format;
|
||||
// try and get the pattern
|
||||
FcPattern *pattern = FcPatternCreate();
|
||||
+ FcPattern *match = NULL;
|
||||
|
||||
FcValue value;
|
||||
value.type = FcTypeString;
|
||||
@@ -977,7 +978,41 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef
|
||||
FcConfigSubstitute(nullptr, pattern, FcMatchPattern);
|
||||
FcDefaultSubstitute(pattern);
|
||||
|
||||
- FcPattern *match = FcFontMatch(nullptr, pattern, &result);
|
||||
+ if (!fid.filename.isEmpty()) {
|
||||
+ // FC_INDEX is ignored during processing in FcFontMatch.
|
||||
+ // So iterate FcPatterns directly and find it out.
|
||||
+ FcFontSet *fcsets[2], *fcfs;
|
||||
+
|
||||
+ fcsets[0] = FcConfigGetFonts(nullptr, FcSetSystem);
|
||||
+ fcsets[1] = FcConfigGetFonts(nullptr, FcSetApplication);
|
||||
+ for (int nset = 0; nset < 2; nset++) {
|
||||
+ fcfs = fcsets[nset];
|
||||
+ for (int fnum = 0; fnum < fcfs->nfont; fnum++) {
|
||||
+ FcPattern *fcpat = fcfs->fonts[fnum];
|
||||
+ FcChar8 *fcfile;
|
||||
+ FcBool variable;
|
||||
+ int fcindex;
|
||||
+
|
||||
+ // FIXME: Ignore a FcPattern which has variable=true at this point.
|
||||
+ if (FcPatternGetBool(fcpat, FC_VARIABLE, 0, &variable) == FcResultMatch &&
|
||||
+ variable == FcTrue)
|
||||
+ continue;
|
||||
+ if (FcPatternGetString(fcpat, FC_FILE, 0, &fcfile) == FcResultMatch &&
|
||||
+ FcPatternGetInteger(fcpat, FC_INDEX, 0, &fcindex) == FcResultMatch) {
|
||||
+ QByteArray f = QByteArray::fromRawData((const char *)fcfile,
|
||||
+ strlen((const char *)fcfile));
|
||||
+ if (f == fid.filename && fcindex == fid.index) {
|
||||
+ // We found it.
|
||||
+ match = FcFontRenderPrepare(nullptr, pattern, fcpat);
|
||||
+ goto bail;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+bail:
|
||||
+ if (!match)
|
||||
+ match = FcFontMatch(nullptr, pattern, &result);
|
||||
if (match) {
|
||||
engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf));
|
||||
|
||||
@@ -997,6 +1032,11 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef
|
||||
antialias = fc_antialias;
|
||||
}
|
||||
|
||||
+ FcBool embolden;
|
||||
+ engine->auto_embolden = true;
|
||||
+ if (FcPatternGetBool(match, FC_EMBOLDEN, 0, &embolden) == FcResultMatch)
|
||||
+ engine->embolden = embolden;
|
||||
+
|
||||
if (antialias) {
|
||||
QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None;
|
||||
if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias))
|
||||
diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
|
||||
index 52ce36b0..9626490b 100644
|
||||
--- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
|
||||
+++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
|
||||
@@ -681,6 +681,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
|
||||
kerning_pairs_loaded = false;
|
||||
transform = false;
|
||||
embolden = false;
|
||||
+ auto_embolden = false;
|
||||
obliquen = false;
|
||||
antialias = true;
|
||||
freetype = nullptr;
|
||||
@@ -748,7 +749,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
|
||||
FT_Set_Transform(face, &matrix, nullptr);
|
||||
freetype->matrix = matrix;
|
||||
// fake bold
|
||||
- if ((fontDef.weight >= QFont::Bold) && !(face->style_flags & FT_STYLE_FLAG_BOLD) && !FT_IS_FIXED_WIDTH(face) && !qEnvironmentVariableIsSet("QT_NO_SYNTHESIZED_BOLD")) {
|
||||
+ if (!auto_embolden && (fontDef.weight >= QFont::Bold) && !(face->style_flags & FT_STYLE_FLAG_BOLD) && !FT_IS_FIXED_WIDTH(face) && !qEnvironmentVariableIsSet("QT_NO_SYNTHESIZED_BOLD")) {
|
||||
if (const TT_OS2 *os2 = reinterpret_cast<const TT_OS2 *>(FT_Get_Sfnt_Table(face, ft_sfnt_os2))) {
|
||||
if (os2->usWeightClass < 700 &&
|
||||
(fontDef.pixelSize < 64 || qEnvironmentVariableIsSet("QT_NO_SYNTHESIZED_BOLD_LIMIT"))) {
|
||||
@@ -2104,6 +2105,7 @@ bool QFontEngineFT::initFromFontEngine(const QFontEngineFT *fe)
|
||||
antialias = fe->antialias;
|
||||
transform = fe->transform;
|
||||
embolden = fe->embolden;
|
||||
+ auto_embolden = fe->auto_embolden;
|
||||
obliquen = fe->obliquen;
|
||||
subpixelType = fe->subpixelType;
|
||||
lcdFilterType = fe->lcdFilterType;
|
||||
diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h
|
||||
index 2e3aef69..4372f913 100644
|
||||
--- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h
|
||||
+++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h
|
||||
@@ -295,6 +295,7 @@ protected:
|
||||
bool cacheEnabled;
|
||||
bool forceAutoHint;
|
||||
bool stemDarkeningDriver;
|
||||
+ bool auto_embolden; // a flag to decide if embolden is set by fontconfig
|
||||
|
||||
private:
|
||||
friend class QFontEngineFTRawFont;
|
@ -1,122 +0,0 @@
|
||||
diff --git a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
|
||||
index 2accf99c..31478c1d 100644
|
||||
--- a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
|
||||
+++ b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
|
||||
@@ -63,7 +63,7 @@ private slots:
|
||||
#endif
|
||||
void doubleSlashInRoot();
|
||||
void setLocale();
|
||||
- void lastModified();
|
||||
+ // void lastModified();
|
||||
void resourcesInStaticPlugins();
|
||||
|
||||
private:
|
||||
@@ -645,19 +645,19 @@ void tst_QResourceEngine::setLocale()
|
||||
QLocale::setDefault(QLocale::system());
|
||||
}
|
||||
|
||||
-void tst_QResourceEngine::lastModified()
|
||||
-{
|
||||
- {
|
||||
- QFileInfo fi(":/");
|
||||
- QVERIFY(fi.exists());
|
||||
- QVERIFY2(!fi.lastModified().isValid(), qPrintable(fi.lastModified().toString()));
|
||||
- }
|
||||
- {
|
||||
- QFileInfo fi(":/search_file.txt");
|
||||
- QVERIFY(fi.exists());
|
||||
- QVERIFY(fi.lastModified().isValid());
|
||||
- }
|
||||
-}
|
||||
+// void tst_QResourceEngine::lastModified()
|
||||
+// {
|
||||
+// {
|
||||
+// QFileInfo fi(":/");
|
||||
+// QVERIFY(fi.exists());
|
||||
+// QVERIFY2(!fi.lastModified().isValid(), qPrintable(fi.lastModified().toString()));
|
||||
+// }
|
||||
+// {
|
||||
+// QFileInfo fi(":/search_file.txt");
|
||||
+// QVERIFY(fi.exists());
|
||||
+// QVERIFY(fi.lastModified().isValid());
|
||||
+// }
|
||||
+// }
|
||||
|
||||
Q_IMPORT_PLUGIN(PluginClass)
|
||||
void tst_QResourceEngine::resourcesInStaticPlugins()
|
||||
diff --git a/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp b/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp
|
||||
index fe63cecc..e1686aea 100644
|
||||
--- a/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp
|
||||
+++ b/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp
|
||||
@@ -46,7 +46,7 @@ private slots:
|
||||
void currentStorage();
|
||||
void storageList();
|
||||
void tempFile();
|
||||
- void caching();
|
||||
+ // void caching();
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -202,34 +202,34 @@ void tst_QStorageInfo::tempFile()
|
||||
QVERIFY(free != storage2.bytesFree());
|
||||
}
|
||||
|
||||
-void tst_QStorageInfo::caching()
|
||||
-{
|
||||
- QTemporaryFile file;
|
||||
- QVERIFY2(file.open(), qPrintable(file.errorString()));
|
||||
-
|
||||
- QStorageInfo storage1(file.fileName());
|
||||
-#ifdef Q_OS_LINUX
|
||||
- if (storage1.fileSystemType() == "btrfs")
|
||||
- QSKIP("This test doesn't work on btrfs, probably due to a btrfs bug");
|
||||
-#endif
|
||||
-
|
||||
- qint64 free = storage1.bytesFree();
|
||||
- QStorageInfo storage2(storage1);
|
||||
- QCOMPARE(free, storage2.bytesFree());
|
||||
- QVERIFY(free != -1);
|
||||
-
|
||||
- file.write(QByteArray(1024*1024, '\0'));
|
||||
- file.flush();
|
||||
-
|
||||
- QCOMPARE(free, storage1.bytesFree());
|
||||
- QCOMPARE(free, storage2.bytesFree());
|
||||
- storage2.refresh();
|
||||
- QCOMPARE(storage1, storage2);
|
||||
- if (free == storage2.bytesFree() && storage2.fileSystemType() == "apfs") {
|
||||
- QEXPECT_FAIL("", "This test is likely to fail on APFS", Continue);
|
||||
- }
|
||||
- QVERIFY(free != storage2.bytesFree());
|
||||
-}
|
||||
+// void tst_QStorageInfo::caching()
|
||||
+// {
|
||||
+// QTemporaryFile file;
|
||||
+// QVERIFY2(file.open(), qPrintable(file.errorString()));
|
||||
+//
|
||||
+// QStorageInfo storage1(file.fileName());
|
||||
+// #ifdef Q_OS_LINUX
|
||||
+// if (storage1.fileSystemType() == "btrfs")
|
||||
+// QSKIP("This test doesn't work on btrfs, probably due to a btrfs bug");
|
||||
+// #endif
|
||||
+//
|
||||
+// qint64 free = storage1.bytesFree();
|
||||
+// QStorageInfo storage2(storage1);
|
||||
+// QCOMPARE(free, storage2.bytesFree());
|
||||
+// QVERIFY(free != -1);
|
||||
+//
|
||||
+// file.write(QByteArray(1024*1024, '\0'));
|
||||
+// file.flush();
|
||||
+//
|
||||
+// QCOMPARE(free, storage1.bytesFree());
|
||||
+// QCOMPARE(free, storage2.bytesFree());
|
||||
+// storage2.refresh();
|
||||
+// QCOMPARE(storage1, storage2);
|
||||
+// if (free == storage2.bytesFree() && storage2.fileSystemType() == "apfs") {
|
||||
+// QEXPECT_FAIL("", "This test is likely to fail on APFS", Continue);
|
||||
+// }
|
||||
+// QVERIFY(free != storage2.bytesFree());
|
||||
+// }
|
||||
#endif
|
||||
|
||||
QTEST_MAIN(tst_QStorageInfo)
|
@ -0,0 +1,30 @@
|
||||
From 111c08d0eaa134652f1f1e602ead1a539614258f Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Macieira <thiago.macieira@intel.com>
|
||||
Date: Mon, 11 Mar 2024 11:24:00 -0400
|
||||
Subject: [PATCH] QFutureInterface: fix build with GCC14/C++20: template-id not
|
||||
allowed
|
||||
|
||||
When declaring a constructor, you must use the injected name, not a
|
||||
template.
|
||||
|
||||
qfutureinterface.h:472:37: error: template-id not allowed for constructor in C++20 [-Werror=template-id-cdtor]
|
||||
|
||||
Pick-to: 6.6 6.7
|
||||
Change-Id: I6818d78a57394e37857bfffd17bbbf2313001cbf
|
||||
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
|
||||
---
|
||||
src/corelib/thread/qfutureinterface.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h
|
||||
index fa5e8ea7bab..180a59a94e7 100644
|
||||
--- a/src/corelib/thread/qfutureinterface.h
|
||||
+++ b/src/corelib/thread/qfutureinterface.h
|
||||
@@ -469,7 +469,7 @@ template <>
|
||||
class QFutureInterface<void> : public QFutureInterfaceBase
|
||||
{
|
||||
public:
|
||||
- explicit QFutureInterface<void>(State initialState = NoState)
|
||||
+ explicit QFutureInterface(State initialState = NoState)
|
||||
: QFutureInterfaceBase(initialState)
|
||||
{ }
|
@ -0,0 +1,13 @@
|
||||
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
|
||||
index 6e01af052c..fc67477ba9 100644
|
||||
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
|
||||
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
|
||||
@@ -868,6 +868,8 @@ QStringList QGenericUnixTheme::themeNames()
|
||||
result.push_back(QLatin1String(QKdeTheme::name));
|
||||
#endif
|
||||
} else if (gtkBasedEnvironments.contains(desktopName)) {
|
||||
+ // prefer the QGnomePlatform theme
|
||||
+ result.push_back(QStringLiteral("qgnomeplatform"));
|
||||
// prefer the GTK3 theme implementation with native dialogs etc.
|
||||
result.push_back(QStringLiteral("gtk3"));
|
||||
// fallback to the generic Gnome theme if loading the GTK3 theme fails
|
Loading…
Reference in new issue