1
0
mirror of https://github.com/danog/patches.git synced 2024-11-30 04:19:34 +01:00
patches/qtbase_5_12_8.diff

1281 lines
51 KiB
Diff
Raw Normal View History

2019-10-11 13:14:43 +02:00
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index 266faca0ed..cf9dafb6d8 100644
2019-10-11 13:14:43 +02:00
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -140,7 +140,8 @@ QMacAutoReleasePool::QMacAutoReleasePool()
{
Class trackerClass = [QMacAutoReleasePoolTracker class];
-#ifdef QT_DEBUG
+// Patch: Disable this debug code because it is very slow.
+#ifdef QT_DEBUG____REMOVED
void *poolFrame = nullptr;
if (__builtin_available(macOS 10.14, iOS 12.0, tvOS 12.0, watchOS 5.0, *)) {
void *frame;
diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index 48060a2c37..fff3271ec9 100644
--- a/src/gui/kernel/qstylehints.cpp
+++ b/src/gui/kernel/qstylehints.cpp
@@ -374,7 +374,11 @@ bool QStyleHints::showIsMaximized() const
*/
bool QStyleHints::showShortcutsInContextMenus() const
{
- return themeableHint(QPlatformTheme::ShowShortcutsInContextMenus, QPlatformIntegration::ShowShortcutsInContextMenus).toBool();
+ // Patch: Always show hotkeys in the standard context menu.
+ // This patch can be removed in 5.13 and later versions.
+ // See: https://bugreports.qt.io/browse/QTBUG-71471
+ return true;
+ // return themeableHint(QPlatformTheme::ShowShortcutsInContextMenus, QPlatformIntegration::ShowShortcutsInContextMenus).toBool();
}
/*!
2019-10-11 13:14:43 +02:00
diff --git a/src/gui/painting/qbezier.cpp b/src/gui/painting/qbezier.cpp
index 65e6063fe4..fcf19a1a63 100644
2019-10-11 13:14:43 +02:00
--- a/src/gui/painting/qbezier.cpp
+++ b/src/gui/painting/qbezier.cpp
@@ -400,6 +400,33 @@ static bool addCircle(const QBezier *b, qreal offset, QBezier *o)
return true;
}
+// Patch: Workaround VS2019 compiler bug, see QTBUG-75280.
+#ifdef Q_OS_WIN
+Q_NEVER_INLINE void QBezier::split(QBezier *firstHalf, QBezier *secondHalf) const
+{
+ Q_ASSERT(firstHalf);
+ Q_ASSERT(secondHalf);
+
+ qreal c = (x2 + x3)*.5;
+ firstHalf->x2 = (x1 + x2)*.5;
+ secondHalf->x3 = (x3 + x4)*.5;
+ firstHalf->x1 = x1;
+ secondHalf->x4 = x4;
+ firstHalf->x3 = (firstHalf->x2 + c)*.5;
+ secondHalf->x2 = (secondHalf->x3 + c)*.5;
+ firstHalf->x4 = secondHalf->x1 = (firstHalf->x3 + secondHalf->x2)*.5;
+
+ c = (y2 + y3)/2;
+ firstHalf->y2 = (y1 + y2)*.5;
+ secondHalf->y3 = (y3 + y4)*.5;
+ firstHalf->y1 = y1;
+ secondHalf->y4 = y4;
+ firstHalf->y3 = (firstHalf->y2 + c)*.5;
+ secondHalf->y2 = (secondHalf->y3 + c)*.5;
+ firstHalf->y4 = secondHalf->y1 = (firstHalf->y3 + secondHalf->y2)*.5;
+}
+#endif // Q_OS_WIN
+
int QBezier::shifted(QBezier *curveSegments, int maxSegments, qreal offset, float threshold) const
{
Q_ASSERT(curveSegments);
diff --git a/src/gui/painting/qbezier_p.h b/src/gui/painting/qbezier_p.h
index f8a91e9ef3..50c60b2d71 100644
2019-10-11 13:14:43 +02:00
--- a/src/gui/painting/qbezier_p.h
+++ b/src/gui/painting/qbezier_p.h
@@ -222,6 +222,8 @@ inline QPointF QBezier::secondDerivedAt(qreal t) const
a * y1 + b * y2 + c * y3 + d * y4);
}
+// Patch: Workaround VS2019 compiler bug, see QTBUG-75280.
+#ifndef Q_OS_WIN
inline void QBezier::split(QBezier *firstHalf, QBezier *secondHalf) const
{
Q_ASSERT(firstHalf);
@@ -245,6 +247,7 @@ inline void QBezier::split(QBezier *firstHalf, QBezier *secondHalf) const
secondHalf->y2 = (secondHalf->y3 + c)*.5;
firstHalf->y4 = secondHalf->y1 = (firstHalf->y3 + secondHalf->y2)*.5;
}
+#endif // Q_OS_WIN
inline void QBezier::parameterSplitLeft(qreal t, QBezier *left)
{
2019-11-07 08:35:33 +01:00
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index b70b29e54e..9519894076 100644
2019-11-07 08:35:33 +01:00
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -6245,6 +6245,91 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
return pixmap;
}
+// Patch: Improved underline with SpellCheck style for macOS and Windows.
+// Added implementation of underline drawing from Chrome.
+static QPixmap generateChromeSpellcheckPixmap(qreal descent, qreal factor, const QPen &pen) {
+ QString key = QLatin1String("ChromeUnderline-")
+ % pen.color().name()
+ % HexString<qreal>(factor)
+ % HexString<qreal>(pen.widthF());
+
+ QPixmap pixmap;
+ if (QPixmapCache::find(key, pixmap)) {
+ return pixmap;
+ }
+ // https://chromium.googlesource.com/chromium/src/+/refs/heads/master/third_party/blink/renderer/core/paint/document_marker_painter.cc
+
+#ifdef Q_OS_MAC
+
+ constexpr qreal kMarkerHeight = 3;
+
+ const qreal height = kMarkerHeight * factor;
+ const qreal width = height * 2;
+
+ pixmap = QPixmap(qCeil(width), qFloor(height) * 2);
+ pixmap.setDevicePixelRatio(qApp->devicePixelRatio());
+ pixmap.fill(Qt::transparent);
+ {
+ QPainter imgPainter(&pixmap);
+ imgPainter.setPen(Qt::NoPen);
+ imgPainter.setBrush(pen.color());
+ imgPainter.setRenderHints(
+ QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
+ imgPainter.drawEllipse(0, 0, qFloor(height), qFloor(height));
+ }
+
+#else
+
+ constexpr qreal kMarkerWidth = 4;
+ constexpr qreal kMarkerHeight = 2;
+
+ const auto x1 = (kMarkerWidth * -3 / 8) * factor;
+ const auto y1 = (kMarkerHeight * 3 / 4) * factor;
+
+ const auto cY = (kMarkerHeight * 1 / 4) * factor;
+
+ const auto c1X1 = (kMarkerWidth * -1 / 8) * factor;
+ const auto c1X2 = (kMarkerWidth * 3 / 8) * factor;
+ const auto c1X3 = (kMarkerWidth * 7 / 8) * factor;
+
+ const auto c2X1 = (kMarkerWidth * 1 / 8) * factor;
+ const auto c2X2 = (kMarkerWidth * 5 / 8) * factor;
+ const auto c2X3 = (kMarkerWidth * 9 / 8) * factor;
+
+ QPainterPath path;
+ path.moveTo(x1, y1);
+ path.cubicTo(c1X1, y1,
+ c1X1, cY,
+ c2X1, cY);
+ path.cubicTo(c1X2, cY,
+ c1X2, y1,
+ c2X2, y1);
+ path.cubicTo(c1X3, y1,
+ c1X3, cY,
+ c2X3, cY);
+
+ pixmap = QPixmap(kMarkerWidth * factor, kMarkerHeight * factor * 2);
+ pixmap.fill(Qt::transparent);
+ {
+ QPen wavePen = pen;
+ wavePen.setCapStyle(Qt::RoundCap);
+ wavePen.setJoinStyle(Qt::RoundJoin);
+ wavePen.setWidthF(1 * factor);
+
+ QPainter imgPainter(&pixmap);
+ imgPainter.setPen(std::move(wavePen));
+ imgPainter.setRenderHint(QPainter::Antialiasing);
+ imgPainter.translate(0, descent - (kMarkerHeight * factor));
+ imgPainter.drawPath(std::move(path));
+ }
+
+#endif
+
+ QPixmapCache::insert(std::move(key), pixmap);
+
+ return pixmap;
+}
+
static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
QTextCharFormat::UnderlineStyle underlineStyle,
QTextItem::RenderFlags flags, qreal width,
@@ -6262,7 +6347,9 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
pen.setWidthF(fe->lineThickness().toReal());
pen.setCapStyle(Qt::FlatCap);
- QLineF line(qFloor(pos.x()), pos.y(), qFloor(pos.x() + width), pos.y());
+ // Patch: Improved underline with SpellCheck style for macOS and Windows.
+ // Slightly move the beginning of the underline to the right.
+ QLineF line(qFloor(pos.x() + 1), pos.y(), qFloor(pos.x() + width), pos.y());
bool wasCompatiblePainting = painter->renderHints()
& QPainter::Qt4CompatiblePainting;
@@ -6273,13 +6360,29 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
const qreal underlineOffset = fe->underlinePosition().toReal();
if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
- QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
- if (theme)
- underlineStyle = QTextCharFormat::UnderlineStyle(theme->themeHint(QPlatformTheme::SpellCheckUnderlineStyle).toInt());
- if (underlineStyle == QTextCharFormat::SpellCheckUnderline) // still not resolved
- underlineStyle = QTextCharFormat::WaveUnderline;
- }
+ const qreal fontFactor = qreal(charFormat.font().pixelSize()) / qreal(10.);
+ painter->save();
+ painter->translate(0, pos.y() + 1);
+ const qreal maxHeight = fe->descent().toReal() - qreal(1);
+
+ QColor uc = charFormat.underlineColor();
+ if (uc.isValid())
+ pen.setColor(uc);
+ const QPixmap wave = generateChromeSpellcheckPixmap(maxHeight, fontFactor, pen);
+ const int descent = qFloor(maxHeight);
+
+ painter->setBrushOrigin(painter->brushOrigin().x(), 0);
+#ifdef Q_OS_MAC
+ const auto h = wave.height() / 2;
+ painter->drawTiledPixmap(
+ QRectF(pos.x(), (descent - h) / 2., qCeil(width), h),
+ wave);
+#else
+ painter->fillRect(pos.x(), 0, qCeil(width), descent, wave);
+#endif
+ painter->restore();
+ } else
if (underlineStyle == QTextCharFormat::WaveUnderline) {
painter->save();
painter->translate(0, pos.y() + 1);
2019-10-11 13:14:43 +02:00
diff --git a/src/gui/text/qinputcontrol.cpp b/src/gui/text/qinputcontrol.cpp
index 3381fdb673..6036f052e9 100644
2019-10-11 13:14:43 +02:00
--- a/src/gui/text/qinputcontrol.cpp
+++ b/src/gui/text/qinputcontrol.cpp
@@ -40,6 +40,10 @@
#include "qinputcontrol_p.h"
#include <QtGui/qevent.h>
+// Patch: Enable Ctrl+key and Ctrl+Shift+key in all locales except German.
+// See https://github.com/telegramdesktop/tdesktop/pull/1185.
+#include <QtCore/QLocale>
+
QT_BEGIN_NAMESPACE
QInputControl::QInputControl(Type type, QObject *parent)
@@ -67,9 +71,16 @@ bool QInputControl::isAcceptableInput(const QKeyEvent *event) const
if (c.category() == QChar::Other_Format)
return true;
- // QTBUG-35734: ignore Ctrl/Ctrl+Shift; accept only AltGr (Alt+Ctrl) on German keyboards
- if (event->modifiers() == Qt::ControlModifier
- || event->modifiers() == (Qt::ShiftModifier | Qt::ControlModifier)) {
+ // Patch: Enable Ctrl+key and Ctrl+Shift+key in all locales except German.
+ // See https://github.com/telegramdesktop/tdesktop/pull/1185.
+ bool skipCtrlAndCtrlShift = false;
+ if (QGuiApplication::inputMethod()->locale().language() == QLocale::German) {
+ if (event->modifiers() == Qt::ControlModifier
+ || event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) {
+ skipCtrlAndCtrlShift = true;
+ }
+ }
+ if (skipCtrlAndCtrlShift) {
return false;
}
diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp
index c88497840f..2b08d13834 100644
--- a/src/gui/text/qtextcursor.cpp
+++ b/src/gui/text/qtextcursor.cpp
@@ -510,14 +510,16 @@ bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor
const int len = blockIt.length() - 1;
if (relativePos >= len)
return false;
- if (engine->atWordSeparator(relativePos)) {
- ++relativePos;
- while (relativePos < len && engine->atWordSeparator(relativePos))
- ++relativePos;
- } else {
- while (relativePos < len && !attributes[relativePos].whiteSpace && !engine->atWordSeparator(relativePos))
- ++relativePos;
- }
+ // Patch: Improved apostrophe processing.
+ relativePos = engine->toEdge(relativePos, len, true);
+ // if (engine->atWordSeparator(relativePos)) {
+ // ++relativePos;
+ // while (relativePos < len && engine->atWordSeparator(relativePos))
+ // ++relativePos;
+ // } else {
+ // while (relativePos < len && !attributes[relativePos].whiteSpace && !engine->atWordSeparator(relativePos))
+ // ++relativePos;
+ // }
newPosition = blockIt.position() + relativePos;
break;
}
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index a7834587b1..cabe897268 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -3028,7 +3028,8 @@ bool QTextEngine::atWordSeparator(int position) const
case '&':
case '^':
case '*':
- case '\'':
+ // Patch: Make the apostrophe a non-separator for words.
+ //case '\'':
case '"':
case '`':
case '~':
@@ -3041,6 +3042,74 @@ bool QTextEngine::atWordSeparator(int position) const
return false;
}
+// Patch: Improved apostrophe processing.
+// We should consider apostrophes as word separators when there is more than
+// one apostrophe in a row, or when the apostrophe is at the beginning or end
+// of the word.
+int QTextEngine::toEdge(int pos, int len, bool isRightDirection) {
+ const auto step = isRightDirection ? 1 : -1;
+ const auto next = isRightDirection ? 0 : -1;
+
+ QCharAttributes *attributes = const_cast<QCharAttributes *>(this->attributes());
+
+ const auto atApostrophe = [&](int position) {
+ return layoutData->string.at(position).unicode() == '\'';
+ };
+
+ const auto atSepOrApost = [&](int position) {
+ return atApostrophe(position) || atWordSeparator(position);
+ };
+
+ const auto inBounds = [&](int position) {
+ return isRightDirection
+ ? position < len
+ : position > 0;
+ };
+
+ const auto atSepOrSpace = [&](int position) {
+ return attributes[position].whiteSpace || atWordSeparator(position);
+ };
+
+ const auto isApostropheInWord = [&](int position) {
+ if (!atApostrophe(position)) {
+ return false;
+ }
+ auto p = position - 1;
+ if (p <= 0 || atSepOrSpace(p)) {
+ return false;
+ }
+ p = position + 1;
+ if (p >= len || atSepOrSpace(p)) {
+ return false;
+ }
+ return true;
+ };
+
+ auto counter = 0;
+ while (inBounds(pos) && atSepOrApost(pos + next)) {
+ counter++;
+ pos += step;
+ }
+ // If it's not the single apostrophe, then that's non-letter part of text.
+ if (counter > 1 || (counter == 1 && !isApostropheInWord(pos - step + next))) {
+ return pos;
+ }
+
+ bool isPrevApostrophe = false;
+ while (inBounds(pos) && !atSepOrSpace(pos + next)) {
+ bool isNextApostrophe = atApostrophe(pos + next);
+ if (isPrevApostrophe && isNextApostrophe) {
+ break;
+ }
+ pos += step;
+ isPrevApostrophe = isNextApostrophe;
+ }
+ if (isPrevApostrophe) {
+ pos += -step;
+ }
+ return pos;
+}
+
void QTextEngine::setPreeditArea(int position, const QString &preeditText)
{
if (preeditText.isEmpty()) {
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index e9187ea605..51997ba066 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -622,6 +622,8 @@ private:
public:
bool atWordSeparator(int position) const;
+ // Patch: Improved apostrophe processing.
+ int toEdge(int pos, int len, bool isRightDirection);
QString elidedText(Qt::TextElideMode mode, const QFixed &width, int flags = 0, int from = 0, int count = -1) const;
2019-10-11 13:14:43 +02:00
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index f3f0caa379..081c5f03c0 100644
2019-10-11 13:14:43 +02:00
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -706,16 +706,22 @@ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const
2019-10-11 13:14:43 +02:00
while (oldPos < len && !attributes[oldPos].graphemeBoundary)
oldPos++;
} else {
- if (oldPos < len && d->atWordSeparator(oldPos)) {
- oldPos++;
- while (oldPos < len && d->atWordSeparator(oldPos))
- oldPos++;
- } else {
- while (oldPos < len && !attributes[oldPos].whiteSpace && !d->atWordSeparator(oldPos))
- oldPos++;
- }
2019-10-11 13:14:43 +02:00
+ // Patch: Skip to the end of the current word, not to the start of the next one.
while (oldPos < len && attributes[oldPos].whiteSpace)
2019-10-11 13:14:43 +02:00
oldPos++;
+ // Patch: Improved apostrophe processing.
+ oldPos = d->toEdge(oldPos, len, true);
+ // if (oldPos < len && d->atWordSeparator(oldPos)) {
+ // oldPos++;
+ // while (oldPos < len && d->atWordSeparator(oldPos))
+ // oldPos++;
+ // } else {
+ // while (oldPos < len && !attributes[oldPos].whiteSpace && !d->atWordSeparator(oldPos))
+ // oldPos++;
+ // }
2019-10-11 13:14:43 +02:00
+ // Patch: Skip to the end of the current word, not to the start of the next one.
+ //while (oldPos < len && attributes[oldPos].whiteSpace)
+ // oldPos++;
}
return oldPos;
@@ -745,14 +751,16 @@ int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const
while (oldPos > 0 && attributes[oldPos - 1].whiteSpace)
oldPos--;
- if (oldPos && d->atWordSeparator(oldPos-1)) {
- oldPos--;
- while (oldPos && d->atWordSeparator(oldPos-1))
- oldPos--;
- } else {
- while (oldPos > 0 && !attributes[oldPos - 1].whiteSpace && !d->atWordSeparator(oldPos-1))
- oldPos--;
- }
+ // Patch: Improved apostrophe processing.
+ oldPos = d->toEdge(oldPos, len, false);
+ // if (oldPos && d->atWordSeparator(oldPos-1)) {
+ // oldPos--;
+ // while (oldPos && d->atWordSeparator(oldPos-1))
+ // oldPos--;
+ // } else {
+ // while (oldPos > 0 && !attributes[oldPos - 1].whiteSpace && !d->atWordSeparator(oldPos-1))
+ // oldPos--;
+ // }
}
2019-10-11 13:14:43 +02:00
return oldPos;
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
index 9e6e5d88c7..8e951a2281 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
2020-05-08 07:19:31 +02:00
@@ -1694,50 +1694,85 @@ HFONT QWindowsFontDatabase::systemFont()
static const char *other_tryFonts[] = {
"Arial",
- "MS UI Gothic",
- "Gulim",
- "SimSun",
- "PMingLiU",
+ "Yu Gothic UI",
+ "Meiryo UI",
+ "Yu Gothic",
+ "Meiryo",
2020-05-02 15:04:15 +02:00
+ "Malgun Gothic",
2020-05-04 05:58:21 +02:00
+ "Microsoft YaHei UI",
+ "Microsoft YaHei",
+ "Microsoft JhengHei UI",
+ "Microsoft JhengHei",
2020-05-08 07:19:31 +02:00
+ "Nirmala UI",
+ "Iskoola Pota",
"Arial Unicode MS",
0
};
static const char *jp_tryFonts [] = {
- "MS UI Gothic",
+ "Yu Gothic UI",
+ "Meiryo UI",
+ "Yu Gothic",
+ "Meiryo",
"Arial",
- "Gulim",
- "SimSun",
- "PMingLiU",
2020-05-02 15:04:15 +02:00
+ "Malgun Gothic",
2020-05-04 05:58:21 +02:00
+ "Microsoft YaHei UI",
+ "Microsoft YaHei",
+ "Microsoft JhengHei UI",
+ "Microsoft JhengHei",
2020-05-08 07:19:31 +02:00
+ "Nirmala UI",
+ "Iskoola Pota",
"Arial Unicode MS",
0
};
static const char *ch_CN_tryFonts [] = {
- "SimSun",
2020-05-04 05:58:21 +02:00
+ "Microsoft YaHei UI",
+ "Microsoft YaHei",
"Arial",
- "PMingLiU",
- "Gulim",
- "MS UI Gothic",
+ "Microsoft JhengHei UI",
+ "Microsoft JhengHei",
2020-05-02 15:04:15 +02:00
+ "Malgun Gothic",
+ "Yu Gothic UI",
+ "Meiryo UI",
+ "Yu Gothic",
+ "Meiryo",
2020-05-08 07:19:31 +02:00
+ "Nirmala UI",
+ "Iskoola Pota",
"Arial Unicode MS",
0
};
static const char *ch_TW_tryFonts [] = {
- "PMingLiU",
+ "Microsoft JhengHei UI",
+ "Microsoft JhengHei",
"Arial",
- "SimSun",
- "Gulim",
- "MS UI Gothic",
2020-05-04 05:58:21 +02:00
+ "Microsoft YaHei UI",
+ "Microsoft YaHei",
2020-05-02 15:04:15 +02:00
+ "Malgun Gothic",
+ "Yu Gothic UI",
+ "Meiryo UI",
+ "Yu Gothic",
+ "Meiryo",
2020-05-08 07:19:31 +02:00
+ "Nirmala UI",
+ "Iskoola Pota",
"Arial Unicode MS",
0
};
static const char *kr_tryFonts[] = {
- "Gulim",
2020-05-02 15:04:15 +02:00
+ "Malgun Gothic",
"Arial",
- "PMingLiU",
- "SimSun",
- "MS UI Gothic",
+ "Microsoft JhengHei UI",
+ "Microsoft JhengHei",
2020-05-04 05:58:21 +02:00
+ "Microsoft YaHei UI",
+ "Microsoft YaHei",
+ "Yu Gothic UI",
+ "Meiryo UI",
+ "Yu Gothic",
+ "Meiryo",
2020-05-08 07:19:31 +02:00
+ "Nirmala UI",
+ "Iskoola Pota",
"Arial Unicode MS",
0
};
2019-11-12 14:07:03 +01:00
diff --git a/src/platformsupport/linuxaccessibility/constant_mappings.cpp b/src/platformsupport/linuxaccessibility/constant_mappings.cpp
index fce2919e73..4a7d0f7d92 100644
2019-11-12 14:07:03 +01:00
--- a/src/platformsupport/linuxaccessibility/constant_mappings.cpp
+++ b/src/platformsupport/linuxaccessibility/constant_mappings.cpp
@@ -79,7 +79,12 @@ quint64 spiStatesFromQState(QAccessible::State state)
if (state.checkStateMixed)
setSpiStateBit(&spiState, ATSPI_STATE_INDETERMINATE);
if (state.readOnly)
+// Patch: Support build with AT-SPI version below 2.16.
+#ifdef ATSPI_STATE_READ_ONLY
setSpiStateBit(&spiState, ATSPI_STATE_READ_ONLY);
+#else // ATSPI_STATE_READ_ONLY
+ unsetSpiStateBit(&spiState, ATSPI_STATE_EDITABLE);
+#endif // ATSPI_STATE_READ_ONLY
// if (state.HotTracked)
if (state.defaultButton)
setSpiStateBit(&spiState, ATSPI_STATE_IS_DEFAULT);
2019-10-11 13:14:43 +02:00
diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
index 81a730232c..42bab9aa4b 100644
2019-10-11 13:14:43 +02:00
--- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
+++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
@@ -273,6 +273,12 @@ bool QComposeInputContext::checkComposeTable()
void QComposeInputContext::commitText(uint character) const
{
+ // Patch: Crash fix when not focused widget still receives input events.
+ if (!m_focusObject) {
+ qWarning("QComposeInputContext::commitText: m_focusObject == nullptr, cannot commit text");
+ return;
+ }
+
QInputMethodEvent event;
event.setCommitString(QChar(character));
QCoreApplication::sendEvent(m_focusObject, &event);
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index 2cf6672da9..ef25bb4541 100644
2019-10-11 13:14:43 +02:00
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -175,7 +175,8 @@ QT_USE_NAMESPACE
if (reflectionDelegate) {
if ([reflectionDelegate respondsToSelector:@selector(applicationShouldTerminate:)])
return [reflectionDelegate applicationShouldTerminate:sender];
- return NSTerminateNow;
+ // Patch: Don't terminate if reflectionDelegate does not respond to that selector, just use the default.
+ //return NSTerminateNow;
}
if ([self canQuit]) {
@@ -252,7 +253,11 @@ QT_USE_NAMESPACE
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
- Q_UNUSED(aNotification);
+ // Patch: We need to catch that notification in delegate.
+ if (reflectionDelegate
+ && [reflectionDelegate respondsToSelector:@selector(applicationDidFinishLaunching:)])
+ [reflectionDelegate applicationDidFinishLaunching:aNotification];
+
inLaunch = false;
if (qEnvironmentVariableIsEmpty("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM")) {
diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.mm b/src/plugins/platforms/cocoa/qcocoakeymapper.mm
index 350ae4b9be..457bb3408d 100644
--- a/src/plugins/platforms/cocoa/qcocoakeymapper.mm
+++ b/src/plugins/platforms/cocoa/qcocoakeymapper.mm
@@ -462,7 +462,8 @@ QList<int> QCocoaKeyMapper::possibleKeys(const QKeyEvent *event) const
Qt::KeyboardModifiers neededMods = ModsTbl[i];
int key = kbItem->qtKey[i];
if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) {
- ret << int(key + (keyMods & ~neededMods));
+ // Patch: Fix non-english layout global shortcuts.
+ ret << int(key + neededMods);
}
}
return ret;
2019-10-11 13:14:43 +02:00
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
index 597cfa8318..579d79734d 100644
2019-10-11 13:14:43 +02:00
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
@@ -96,12 +96,17 @@ QT_USE_NAMESPACE
@interface QT_MANGLE_NAMESPACE(QNSStatusItem) : NSObject <NSUserNotificationCenterDelegate>
@property (nonatomic, assign) QCocoaMenu *menu;
+// Patch: Create a rich os x tray icon (pixel-perfect, theme switching).
+@property (nonatomic, assign) bool menuVisible;
+@property (nonatomic, readonly) bool iconSelected;
@property (nonatomic, assign) QIcon icon;
@property (nonatomic, readonly) NSStatusItem *item;
@property (nonatomic, readonly) QRectF geometry;
- (instancetype)initWithSysTray:(QCocoaSystemTrayIcon *)systray;
- (void)triggerSelector:(id)sender button:(Qt::MouseButton)mouseButton;
- (void)doubleClickSelector:(id)sender;
+- (void)setIconSelected:(bool)selected;
+- (bool)hasMenu;
@end
@interface QT_MANGLE_NAMESPACE(QNSImageView) : NSImageView
@@ -173,7 +178,10 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
// (device independent pixels). The menu height on past and
// current OS X versions is 22 points. Provide some future-proofing
// by deriving the icon height from the menu height.
- const int padding = 4;
+
+ // Patch: Create a rich os x tray icon (pixel-perfect, theme switching).
+ const int padding = 0;
+
const int menuHeight = [[NSStatusBar systemStatusBar] thickness];
const int maxImageHeight = menuHeight - padding;
@@ -183,8 +191,12 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
// devicePixelRatio for the "best" screen on the system.
qreal devicePixelRatio = qApp->devicePixelRatio();
const int maxPixmapHeight = maxImageHeight * devicePixelRatio;
+
+ // Patch: Create a rich os x tray icon (pixel-perfect, theme switching).
+ const QIcon::Mode mode = m_sys->item.iconSelected ? QIcon::Selected : QIcon::Normal;
+
QSize selectedSize;
- Q_FOREACH (const QSize& size, sortByHeight(icon.availableSizes())) {
+ Q_FOREACH (const QSize& size, sortByHeight(icon.availableSizes(mode))) {
// Select a pixmap based on the height. We want the largest pixmap
// with a height smaller or equal to maxPixmapHeight. The pixmap
// may rectangular; assume it has a reasonable size. If there is
@@ -200,9 +212,9 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
// Handle SVG icons, which do not return anything for availableSizes().
if (!selectedSize.isValid())
- selectedSize = icon.actualSize(QSize(maxPixmapHeight, maxPixmapHeight));
+ selectedSize = icon.actualSize(QSize(maxPixmapHeight, maxPixmapHeight), mode);
- QPixmap pixmap = icon.pixmap(selectedSize);
+ QPixmap pixmap = icon.pixmap(selectedSize, mode);
// Draw a low-resolution icon if there is not enough pixels for a retina
// icon. This prevents showing a small icon on retina displays.
@@ -301,6 +313,10 @@ QT_END_NAMESPACE
{
self.down = NO;
+ // Patch: Create a rich os x tray icon (pixel-perfect, theme switching).
+ [self.parent setIconSelected:false];
+ self.parent.menuVisible = false;
+
[self setNeedsDisplay:YES];
}
@@ -310,6 +326,9 @@ QT_END_NAMESPACE
int clickCount = [mouseEvent clickCount];
[self setNeedsDisplay:YES];
+ // Patch: Create a rich os x tray icon (pixel-perfect, theme switching).
+ [self.parent setIconSelected:((clickCount != 2) && [self.parent hasMenu])];
+
if (clickCount == 2) {
[self menuTrackingDone:nil];
[self.parent doubleClickSelector:self];
@@ -326,6 +345,10 @@ QT_END_NAMESPACE
- (void)mouseUp:(NSEvent *)mouseEvent
{
Q_UNUSED(mouseEvent);
+
+ // Patch: Create a rich os x tray icon (pixel-perfect, theme switching).
+ [self.parent setIconSelected:false];
+
[self menuTrackingDone:nil];
}
@@ -337,6 +360,10 @@ QT_END_NAMESPACE
- (void)rightMouseUp:(NSEvent *)mouseEvent
{
Q_UNUSED(mouseEvent);
+
+ // Patch: Create a rich os x tray icon (pixel-perfect, theme switching).
+ [self.parent setIconSelected:false];
+
[self menuTrackingDone:nil];
}
@@ -352,7 +379,8 @@ QT_END_NAMESPACE
}
- (void)drawRect:(NSRect)rect {
- [[self.parent item] drawStatusBarBackgroundInRect:rect withHighlight:self.down];
+ // Patch: Create a rich os x tray icon (pixel-perfect, theme switching).
+ [[self.parent item] drawStatusBarBackgroundInRect:rect withHighlight:([self.parent hasMenu] && self.down)];
[super drawRect:rect];
}
@end
@@ -372,6 +400,10 @@ QT_END_NAMESPACE
if (self) {
item = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
menu = nullptr;
+
+ // Patch: Create a rich os x tray icon (pixel-perfect, theme switching).
+ self.menuVisible = false;
+
systray = sys;
imageCell = [[QNSImageView alloc] initWithParent:self];
[item setView: imageCell];
@@ -382,6 +414,11 @@ QT_END_NAMESPACE
- (void)dealloc {
[[NSStatusBar systemStatusBar] removeStatusItem:item];
[[NSNotificationCenter defaultCenter] removeObserver:imageCell];
+
+ // Patch: Fix crash in macOS 10.14.
+ // Somehow item and imageCell are retained and attempt to be drawn if left in view.
+ [item setView: nil];
+
imageCell.parent = nil;
[imageCell release];
[item release];
@@ -416,6 +453,10 @@ QT_END_NAMESPACE
selector:@selector(menuTrackingDone:)
name:NSMenuDidEndTrackingNotification
object:m];
+
+ // Patch: Create a rich os x tray icon (pixel-perfect, theme switching).
+ self.menuVisible = true;
+
[item popUpStatusItemMenu: m];
}
}
@@ -427,6 +468,15 @@ QT_END_NAMESPACE
emit systray->activated(QPlatformSystemTrayIcon::DoubleClick);
}
+- (void)setIconSelected:(bool)selected {
+ _iconSelected = selected;
+ systray->updateIcon(icon);
+}
+
+- (bool)hasMenu {
+ return menu != nil;
+}
+
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification {
Q_UNUSED(center);
Q_UNUSED(notification);
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 3008a056a2..d98eade4a3 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -499,6 +499,15 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
// Select base window type. Note that the value of NSBorderlessWindowMask is 0.
NSUInteger styleMask = (frameless || !resizable) ? NSWindowStyleMaskBorderless : NSWindowStyleMaskResizable;
+ // Patch: allow creating panels floating on all spaces in macOS.
+ // If you call "setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary" before
+ // setting the "NSWindowStyleMaskNonactivatingPanel" bit in the style mask it won't work after that.
+ // So we need a way to set that bit before Qt sets collection behavior the way it does.
+ QVariant nonactivatingPanelMask = window()->property("_td_macNonactivatingPanelMask");
+ if (nonactivatingPanelMask.isValid() && nonactivatingPanelMask.toBool()) {
+ styleMask |= NSWindowStyleMaskNonactivatingPanel;
+ }
+
if (frameless) {
// No further customizations for frameless since there are no window decorations.
} else if (flags & Qt::CustomizeWindowHint) {
2019-10-11 13:14:43 +02:00
diff --git a/src/plugins/platforms/cocoa/qnsview_keys.mm b/src/plugins/platforms/cocoa/qnsview_keys.mm
index ad751279bb..9a9d19693e 100644
2019-10-11 13:14:43 +02:00
--- a/src/plugins/platforms/cocoa/qnsview_keys.mm
+++ b/src/plugins/platforms/cocoa/qnsview_keys.mm
@@ -86,21 +86,29 @@
quint32 nativeVirtualKey = [nsevent keyCode];
QChar ch = QChar::ReplacementCharacter;
- int keyCode = Qt::Key_unknown;
-
- // If a dead key occurs as a result of pressing a key combination then
- // characters will have 0 length, but charactersIgnoringModifiers will
- // have a valid character in it. This enables key combinations such as
- // ALT+E to be used as a shortcut with an English keyboard even though
- // pressing ALT+E will give a dead key while doing normal text input.
- if ([characters length] != 0 || [charactersIgnoringModifiers length] != 0) {
- auto ctrlOrMetaModifier = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) ? Qt::ControlModifier : Qt::MetaModifier;
- if (((modifiers & ctrlOrMetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0))
- ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
- else if ([characters length] != 0)
- ch = QChar([characters characterAtIndex:0]);
- keyCode = [self convertKeyCode:ch];
- }
+
+ // Patch: Fix Alt+.. shortcuts in OS X. See https://bugreports.qt.io/browse/QTBUG-42584 at the end.
+ if ([characters length] != 0)
+ ch = QChar([characters characterAtIndex:0]);
+ else if ([charactersIgnoringModifiers length] != 0 && ((modifiers & Qt::MetaModifier) || (modifiers & Qt::AltModifier)))
+ ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
+
+ int keyCode = [self convertKeyCode:ch];
+ // int keyCode = Qt::Key_unknown;
+
+ // // If a dead key occurs as a result of pressing a key combination then
+ // // characters will have 0 length, but charactersIgnoringModifiers will
+ // // have a valid character in it. This enables key combinations such as
+ // // ALT+E to be used as a shortcut with an English keyboard even though
+ // // pressing ALT+E will give a dead key while doing normal text input.
+ // if ([characters length] != 0 || [charactersIgnoringModifiers length] != 0) {
+ // auto ctrlOrMetaModifier = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) ? Qt::ControlModifier : Qt::MetaModifier;
+ // if (((modifiers & ctrlOrMetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0))
+ // ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
+ // else if ([characters length] != 0)
+ // ch = QChar([characters characterAtIndex:0]);
+ // keyCode = [self convertKeyCode:ch];
+ // }
// we will send a key event unless the input method sets m_sendKeyEvent to false
m_sendKeyEvent = true;
@@ -196,6 +204,23 @@
[super keyUp:nsevent];
}
+// Patch: Enable Ctrl+Tab and Ctrl+Shift+Tab / Ctrl+Backtab handle in-app.
+- (BOOL)performKeyEquivalent:(NSEvent *)nsevent
+{
+ NSString *chars = [nsevent charactersIgnoringModifiers];
+
+ if ([nsevent type] == NSKeyDown && [chars length] > 0) {
+ QChar ch = [chars characterAtIndex:0];
+ Qt::Key qtKey = qt_mac_cocoaKey2QtKey(ch);
+ if ([nsevent modifierFlags] & NSControlKeyMask
+ && (qtKey == Qt::Key_Tab || qtKey == Qt::Key_Backtab)) {
+ [self handleKeyEvent:nsevent eventType:int(QEvent::KeyPress)];
+ return YES;
+ }
+ }
+ return [super performKeyEquivalent:nsevent];
+}
+
- (void)cancelOperation:(id)sender
{
Q_UNUSED(sender);
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 9de3268fc8..8b281c95db 100644
2019-10-11 13:14:43 +02:00
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -1179,7 +1179,14 @@ void QWindowsNativeFileDialogBase::selectFile(const QString &fileName) const
// Hack to prevent CLSIDs from being set as file name due to
// QFileDialogPrivate::initialSelection() being QString-based.
if (!isClsid(fileName))
- m_fileDialog->SetFileName((wchar_t*)fileName.utf16());
+ // Patch: Fix handle of full fileName.
+ {
+ QString file = QDir::toNativeSeparators(fileName);
+ int lastBackSlash = file.lastIndexOf(QChar::fromLatin1('\\'));
+ if (lastBackSlash >= 0)
+ file = file.mid(lastBackSlash + 1);
+ m_fileDialog->SetFileName((wchar_t*)file.utf16());;
+ }
}
// Return the index of the selected filter, accounting for QFileDialog
@@ -1456,7 +1463,8 @@ static QString createTemporaryItemCopy(QWindowsShellItem &qItem, QString *errorM
2019-10-11 13:14:43 +02:00
static QUrl itemToDialogUrl(QWindowsShellItem &qItem, QString *errorMessage)
{
QUrl url = qItem.url();
- if (url.isLocalFile() || url.scheme().startsWith(QLatin1String("http")))
+ // Patch: Make loaded 'http' resources copy.
+ if (url.isLocalFile()/*|| url.scheme().startsWith(QLatin1String("http"))*/)
return url;
const QString path = qItem.path();
if (path.isEmpty() && !qItem.isDir() && qItem.canStream()) {
diff --git a/src/plugins/platforms/windows/qwindowsservices.cpp b/src/plugins/platforms/windows/qwindowsservices.cpp
index 9504513a5e..811f3d62bd 100644
2019-10-11 13:14:43 +02:00
--- a/src/plugins/platforms/windows/qwindowsservices.cpp
+++ b/src/plugins/platforms/windows/qwindowsservices.cpp
@@ -125,6 +125,10 @@ static inline bool launchMail(const QUrl &url)
command.prepend(doubleQuote);
}
}
+
+ // Patch: Fix mail launch if no param is expected in this command.
+ if (command.indexOf(QStringLiteral("%1")) < 0) return false;
+
// Pass the url as the parameter. Should use QProcess::startDetached(),
// but that cannot handle a Windows command line [yet].
command.replace(QLatin1String("%1"), url.toString(QUrl::FullyEncoded));
2019-10-20 10:36:41 +02:00
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 7d511bf0d7..da3879cb56 100644
2019-10-20 10:36:41 +02:00
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1351,7 +1351,8 @@ void QWindowsWindow::destroyWindow()
for (QWindow *w : tlw) {
if (w->transientParent() == window()) {
if (QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(w))
- tw->updateTransientParent();
+ // Patch: Fix possibility of add / remove taskbar icon of the window.
+ tw->clearTransientParent();
}
}
QWindowsContext *context = QWindowsContext::instance();
@@ -1579,6 +1580,19 @@ void QWindowsWindow::updateTransientParent() const
// window is found, which can cause issues with modality. Loop up to top level.
while (newTransientParent && (GetWindowLongPtr(newTransientParent, GWL_STYLE) & WS_CHILD) != 0)
newTransientParent = GetParent(newTransientParent);
+ // Patch: Fix possibility of add / remove taskbar icon of the window.
+ if (newTransientParent && newTransientParent != oldTransientParent)
+ SetWindowLongPtr(m_data.hwnd, GWL_HWNDPARENT, (LONG_PTR)newTransientParent);
+}
+
+// Patch: Fix possibility of add / remove taskbar icon of the window.
+void QWindowsWindow::clearTransientParent() const
+{
+ if (window()->type() == Qt::Popup)
+ return; // QTBUG-34503, // a popup stays on top, no parent, see also WindowCreationData::fromWindow().
+ // Update transient parent.
+ const HWND oldTransientParent = GetWindow(m_data.hwnd, GW_OWNER);
+ HWND newTransientParent = 0;
if (newTransientParent != oldTransientParent)
SetWindowLongPtr(m_data.hwnd, GWL_HWNDPARENT, LONG_PTR(newTransientParent));
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index ce67e46df3..a60edc151f 100644
2019-10-20 10:36:41 +02:00
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -353,6 +353,10 @@ private:
inline void setWindowState_sys(Qt::WindowStates newState);
inline void setParent_sys(const QPlatformWindow *parent);
inline void updateTransientParent() const;
+
+ // Patch: Fix possibility of add / remove taskbar icon of the window.
+ inline void clearTransientParent() const;
+
void destroyWindow();
inline bool isDropSiteEnabled() const { return m_dropTarget != 0; }
void setDropSiteEnabled(bool enabled);
2020-05-19 17:48:02 +02:00
diff --git a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp
index c64a02fa0c..38198e61ba 100644
2020-05-19 17:48:02 +02:00
--- a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp
+++ b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp
@@ -45,6 +45,7 @@
#include <qcolor.h>
#include <qdebug.h>
#include <qfont.h>
+#include <qfileinfo.h>
#include <private/qguiapplication_p.h>
#include <qpa/qplatformfontdatabase.h>
@@ -57,6 +58,16 @@
QT_BEGIN_NAMESPACE
+// GTK file chooser image preview: thanks to Chromium
+
+// The size of the preview we display for selected image files. We set height
+// larger than width because generally there is more free space vertically
+// than horiztonally (setting the preview image will alway expand the width of
+// the dialog, but usually not the height). The image's aspect ratio will always
+// be preserved.
+#define PREVIEW_WIDTH 256
+#define PREVIEW_HEIGHT 512
+
class QGtk3Dialog : public QWindow
{
Q_OBJECT
@@ -250,12 +261,21 @@ QGtk3FileDialogHelper::QGtk3FileDialogHelper()
g_signal_connect(GTK_FILE_CHOOSER(d->gtkDialog()), "selection-changed", G_CALLBACK(onSelectionChanged), this);
g_signal_connect_swapped(GTK_FILE_CHOOSER(d->gtkDialog()), "current-folder-changed", G_CALLBACK(onCurrentFolderChanged), this);
g_signal_connect_swapped(GTK_FILE_CHOOSER(d->gtkDialog()), "notify::filter", G_CALLBACK(onFilterChanged), this);
2020-05-19 17:48:02 +02:00
+
+ previewWidget = gtk_image_new();
+ g_signal_connect(G_OBJECT(d->gtkDialog()), "update-preview", G_CALLBACK(onUpdatePreview), this);
+ gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(d->gtkDialog()), previewWidget);
2020-05-19 17:48:02 +02:00
}
QGtk3FileDialogHelper::~QGtk3FileDialogHelper()
{
2020-05-19 17:48:02 +02:00
}
+GtkImage *QGtk3FileDialogHelper::previewImage() const
+{
+ return GTK_IMAGE(previewWidget);
+}
+
bool QGtk3FileDialogHelper::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent)
{
_dir.clear();
@@ -390,6 +410,33 @@ void QGtk3FileDialogHelper::onFilterChanged(QGtk3FileDialogHelper *dialog)
emit dialog->filterSelected(dialog->selectedNameFilter());
}
+void QGtk3FileDialogHelper::onUpdatePreview(GtkDialog *gtkDialog, QGtk3FileDialogHelper *helper)
+{
+ gchar *filename = gtk_file_chooser_get_preview_filename(GTK_FILE_CHOOSER(gtkDialog));
2020-05-19 17:48:02 +02:00
+ if (!filename) {
+ gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(gtkDialog), false);
2020-05-19 17:48:02 +02:00
+ return;
+ }
+
+ // Don't attempt to open anything which isn't a regular file. If a named pipe,
+ // this may hang. See https://crbug.com/534754.
+ QFileInfo fileinfo(filename);
+ if (!fileinfo.exists() || !fileinfo.isFile()) {
+ g_free(filename);
+ gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(gtkDialog), false);
2020-05-19 17:48:02 +02:00
+ return;
+ }
+
+ // This will preserve the image's aspect ratio.
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_size(filename, PREVIEW_WIDTH, PREVIEW_HEIGHT, 0);
+ g_free(filename);
+ if (pixbuf) {
+ gtk_image_set_from_pixbuf(helper->previewImage(), pixbuf);
2020-05-19 17:48:02 +02:00
+ g_object_unref(pixbuf);
+ }
+ gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(gtkDialog), pixbuf ? true : false);
2020-05-19 17:48:02 +02:00
+}
+
static GtkFileChooserAction gtkFileChooserAction(const QSharedPointer<QFileDialogOptions> &options)
2020-05-19 17:48:02 +02:00
{
switch (options->fileMode()) {
diff --git a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.h b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.h
index e78a7fc6d1..8963dd7086 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.h
+++ b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.h
@@ -47,6 +47,8 @@
#include <QtCore/qstring.h>
#include <qpa/qplatformdialoghelper.h>
+typedef struct _GtkWidget GtkWidget;
+typedef struct _GtkImage GtkImage;
typedef struct _GtkDialog GtkDialog;
typedef struct _GtkFileFilter GtkFileFilter;
@@ -88,6 +90,8 @@ public:
QGtk3FileDialogHelper();
~QGtk3FileDialogHelper();
+ GtkImage *previewImage() const;
+
bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) override;
void exec() override;
void hide() override;
@@ -108,6 +112,7 @@ private:
static void onSelectionChanged(GtkDialog *dialog, QGtk3FileDialogHelper *helper);
static void onCurrentFolderChanged(QGtk3FileDialogHelper *helper);
static void onFilterChanged(QGtk3FileDialogHelper *helper);
+ static void onUpdatePreview(GtkDialog *dialog, QGtk3FileDialogHelper *helper);
void applyOptions();
void setNameFilters(const QStringList &filters);
void selectFileInternal(const QUrl &filename);
@@ -118,6 +123,7 @@ private:
QHash<QString, GtkFileFilter*> _filters;
QHash<GtkFileFilter*, QString> _filterNames;
QScopedPointer<QGtk3Dialog> d;
+ GtkWidget *previewWidget;
};
class QGtk3FontDialogHelper : public QPlatformFontDialogHelper
2020-05-19 17:48:02 +02:00
diff --git a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
index 077955eb4e..5c8a3dddf7 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
+++ b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
@@ -153,7 +153,7 @@ bool QGtk3Theme::usePlatformNativeDialog(DialogType type) const
case ColorDialog:
return true;
case FileDialog:
- return useNativeFileDialog();
+ return true;
case FontDialog:
return true;
default:
@@ -167,8 +167,6 @@ QPlatformDialogHelper *QGtk3Theme::createPlatformDialogHelper(DialogType type) c
case ColorDialog:
return new QGtk3ColorDialogHelper;
case FileDialog:
- if (!useNativeFileDialog())
- return nullptr;
return new QGtk3FileDialogHelper;
case FontDialog:
return new QGtk3FontDialogHelper;
diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
index fb65f6d909..66c3a54a07 100644
--- a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
+++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
@@ -57,9 +57,11 @@ public:
~QXdgDesktopPortalThemePrivate()
{
delete baseTheme;
+ delete gtkTheme;
}
QPlatformTheme *baseTheme;
+ QPlatformTheme *gtkTheme;
};
QXdgDesktopPortalTheme::QXdgDesktopPortalTheme()
@@ -85,11 +87,17 @@ QXdgDesktopPortalTheme::QXdgDesktopPortalTheme()
break;
}
// No error message; not having a theme plugin is allowed.
+
+ // Try to use gtk's open directory dialog if there are no fallback theme
+ d->gtkTheme = QPlatformThemeFactory::create(QLatin1String("gtk3"), nullptr);
}
// 3) Fall back on the built-in "null" platform theme.
if (!d->baseTheme)
d->baseTheme = new QPlatformTheme;
+
+ if (!d->gtkTheme)
+ d->gtkTheme = new QPlatformTheme;
}
QPlatformMenuItem* QXdgDesktopPortalTheme::createPlatformMenuItem() const
@@ -133,6 +141,8 @@ QPlatformDialogHelper* QXdgDesktopPortalTheme::createPlatformDialogHelper(Dialog
if (type == FileDialog) {
if (d->baseTheme->usePlatformNativeDialog(type))
return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->baseTheme->createPlatformDialogHelper(type)));
+ else if (d->gtkTheme->usePlatformNativeDialog(type))
+ return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->gtkTheme->createPlatformDialogHelper(type)));
return new QXdgDesktopPortalFileDialog;
}
2019-10-11 13:14:43 +02:00
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index bf339ca5c5..4cdf9189ad 100644
2019-10-11 13:14:43 +02:00
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -5161,6 +5161,17 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
return; // Fully transparent.
Q_D(QWidget);
+
+ // Patch: save and restore dirtyOpaqueChildren field.
+ //
+ // Just like in QWidget::grab() this field should be restored
+ // after the d->render() call, because it will be set to 1 and
+ // opaqueChildren field will be filled with empty region in
+ // case the widget is hidden (because all the opaque children
+ // will be skipped in isVisible() check).
+ //
+ const bool oldDirtyOpaqueChildren = d->dirtyOpaqueChildren;
+
const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
const QRegion toBePainted = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
: sourceRegion;
@@ -5182,6 +5193,10 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
if (!inRenderWithPainter && (opacity < 1.0 || (target->devType() == QInternal::Printer))) {
d->render_helper(painter, targetOffset, toBePainted, renderFlags);
d->extra->inRenderWithPainter = inRenderWithPainter;
+
+ // Patch: save and restore dirtyOpaqueChildren field.
+ d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
+
return;
}
@@ -5214,6 +5229,9 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
d->setSharedPainter(oldPainter);
d->extra->inRenderWithPainter = inRenderWithPainter;
+
+ // Patch: save and restore dirtyOpaqueChildren field.
+ d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
}
static void sendResizeEvents(QWidget *target)
@@ -8968,7 +8986,8 @@ bool QWidget::event(QEvent *event)
case QEvent::KeyPress: {
QKeyEvent *k = (QKeyEvent *)event;
bool res = false;
- if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
+ // Patch: Enable Ctrl+Tab and Ctrl+Shift+Tab / Ctrl+Backtab handle in-app.
+ if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier))) {
if (k->key() == Qt::Key_Backtab
|| (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
res = focusNextPrevChild(false);
diff --git a/src/widgets/util/qsystemtrayicon_qpa.cpp b/src/widgets/util/qsystemtrayicon_qpa.cpp
index c0bf058681..1c8b627d01 100644
2019-10-11 13:14:43 +02:00
--- a/src/widgets/util/qsystemtrayicon_qpa.cpp
+++ b/src/widgets/util/qsystemtrayicon_qpa.cpp
@@ -93,6 +93,10 @@ void QSystemTrayIconPrivate::updateMenu_sys()
if (qpa_sys && menu) {
addPlatformMenu(menu);
qpa_sys->updateMenu(menu->platformMenu());
+
+ // Patch: Create a rich os x tray icon (pixel-perfect, theme switching).
+ } else if (qpa_sys) {
+ qpa_sys->updateMenu(nullptr);
}
#endif
}
diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp
index 598d173144..fd2e636563 100644
2019-10-11 13:14:43 +02:00
--- a/src/widgets/widgets/qabstractscrollarea.cpp
+++ b/src/widgets/widgets/qabstractscrollarea.cpp
@@ -655,15 +655,21 @@ scrolling range.
QSize QAbstractScrollArea::maximumViewportSize() const
{
Q_D(const QAbstractScrollArea);
- int hsbExt = d->hbar->sizeHint().height();
- int vsbExt = d->vbar->sizeHint().width();
+ // Patch: Count the sizeHint of the bar only if it is displayed.
+ //int hsbExt = d->hbar->sizeHint().height();
+ //int vsbExt = d->vbar->sizeHint().width();
int f = 2 * d->frameWidth;
QSize max = size() - QSize(f + d->left + d->right, f + d->top + d->bottom);
- if (d->vbarpolicy == Qt::ScrollBarAlwaysOn)
+ // Patch: Count the sizeHint of the bar only if it is displayed.
+ if (d->vbarpolicy == Qt::ScrollBarAlwaysOn) {
+ int vsbExt = d->vbar->sizeHint().width();
max.rwidth() -= vsbExt;
- if (d->hbarpolicy == Qt::ScrollBarAlwaysOn)
+ }
+ if (d->hbarpolicy == Qt::ScrollBarAlwaysOn) {
+ int hsbExt = d->hbar->sizeHint().height();
max.rheight() -= hsbExt;
+ }
return max;
}