summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/accessible/linux/atspiadaptor.cpp15
-rw-r--r--src/gui/accessible/qaccessible.cpp78
-rw-r--r--src/gui/accessible/qaccessible_base.h3
-rw-r--r--src/gui/accessible/qaccessiblehelper.cpp77
-rw-r--r--src/gui/accessible/qaccessiblehelper_p.h18
-rw-r--r--src/gui/configure.cmake11
-rw-r--r--src/gui/doc/src/richtext.qdoc6
-rw-r--r--src/gui/image/qimage.cpp5
-rw-r--r--src/gui/image/qplatformpixmap.h7
-rw-r--r--src/gui/itemmodels/qfilesystemmodel.cpp9
-rw-r--r--src/gui/kernel/qguiapplication.cpp10
-rw-r--r--src/gui/kernel/qwindow.cpp6
-rw-r--r--src/gui/painting/qpainterpath.cpp11
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp2
-rw-r--r--src/gui/platform/darwin/qappleiconengine.mm188
-rw-r--r--src/gui/platform/darwin/qapplekeymapper.mm153
-rw-r--r--src/gui/rhi/qrhigles2.cpp2
-rw-r--r--src/gui/rhi/qrhigles2_p.h1
-rw-r--r--src/gui/rhi/qrhivulkan.cpp12
-rw-r--r--src/gui/text/qfont_p.h4
-rw-r--r--src/gui/text/qtextengine.cpp61
-rw-r--r--src/gui/text/qtextengine_p.h4
-rw-r--r--src/gui/vulkan/qvulkanwindow.cpp13
23 files changed, 419 insertions, 277 deletions
diff --git a/src/gui/accessible/linux/atspiadaptor.cpp b/src/gui/accessible/linux/atspiadaptor.cpp
index e91539d6ee3..dad0ac2b74a 100644
--- a/src/gui/accessible/linux/atspiadaptor.cpp
+++ b/src/gui/accessible/linux/atspiadaptor.cpp
@@ -1688,6 +1688,17 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
sendReply(connection, message, QVariant::fromValue(QDBusVariant(interface->text(QAccessible::Help))));
} else if (function == "GetState"_L1) {
quint64 spiState = spiStatesFromQState(interface->state());
+ if (QAccessibleAttributesInterface *attributesIface = interface->attributesInterface()) {
+ const QVariant orientationVariant =
+ attributesIface->attributeValue(QAccessible::Attribute::Orientation);
+ if (orientationVariant.isValid()) {
+ Q_ASSERT(orientationVariant.canConvert<Qt::Orientation>());
+ const Qt::Orientation orientation = orientationVariant.value<Qt::Orientation>();
+ setSpiStateBit(&spiState,
+ orientation == Qt::Horizontal ? ATSPI_STATE_HORIZONTAL
+ : ATSPI_STATE_VERTICAL);
+ }
+ }
if (interface->tableInterface()) {
// For tables, setting manages_descendants should
// indicate to the client that it cannot cache these
@@ -1877,7 +1888,7 @@ void AtSpiAdaptor::addMatchingDescendants(QList<QAccessibleInterface *> &matches
const QSpiMatchRuleMatcher &matcher, bool invert,
int count, bool traverse)
{
- if (!accessible || matches.size() >= count)
+ if (!accessible || (count != 0 && matches.size() >= count))
return;
const int childCount = accessible->childCount();
@@ -1889,7 +1900,7 @@ void AtSpiAdaptor::addMatchingDescendants(QList<QAccessibleInterface *> &matches
if (traverse)
addMatchingDescendants(matches, child, matcher, invert, count, traverse);
- if (matches.size() >= count)
+ if (count != 0 && matches.size() >= count)
return;
}
}
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index eeb06c535b8..30ebe90da0b 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -458,6 +458,9 @@ Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
differs from the application's default locale, e.g. for documents
or paragraphs within a document that use a language that differs
from the application's user interface language.
+ \value [since 6.11] Orientation value type: \a Qt::Orientation
+ Orientation of the element. This attribute conceptually matches
+ the "aria-orientation" property in ARIA.
\sa QAccessibleAttributesInterface
*/
@@ -968,9 +971,21 @@ void QAccessible::updateAccessibility(QAccessibleEvent *event)
pfAccessibility->notifyAccessibilityUpdate(event);
}
+static std::pair<int, int> qAccessibleTextBoundaryHelperHelper(QTextCursor &cursor,
+ QTextCursor::MoveOperation start,
+ QTextCursor::MoveOperation end)
+{
+ std::pair<int, int> result;
+ cursor.movePosition(start, QTextCursor::MoveAnchor);
+ result.first = cursor.position();
+ cursor.movePosition(end, QTextCursor::KeepAnchor);
+ result.second = cursor.position();
+ return result;
+}
+
/*!
\internal
- \brief getBoundaries is a helper function to find the accessible text boundaries for QTextCursor based documents.
+ \brief qAccessibleTextBoundaryHelper is a helper function to find the accessible text boundaries for QTextCursor based documents.
\param documentCursor a valid cursor bound to the document (not null). It needs to ba at the position to look for the boundary
\param boundaryType the type of boundary to find
\return the boundaries as pair
@@ -979,32 +994,20 @@ std::pair< int, int > QAccessible::qAccessibleTextBoundaryHelper(const QTextCurs
{
Q_ASSERT(!offsetCursor.isNull());
- QTextCursor endCursor = offsetCursor;
- endCursor.movePosition(QTextCursor::End);
- int characterCount = endCursor.position();
-
- std::pair<int, int> result;
QTextCursor cursor = offsetCursor;
switch (boundaryType) {
case CharBoundary:
- result.first = cursor.position();
- cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
- result.second = cursor.position();
- break;
+ return qAccessibleTextBoundaryHelperHelper(cursor, QTextCursor::NoMove,
+ QTextCursor::NextCharacter);
case WordBoundary:
- cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
- result.first = cursor.position();
- cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
- result.second = cursor.position();
- break;
+ return qAccessibleTextBoundaryHelperHelper(cursor, QTextCursor::StartOfWord,
+ QTextCursor::EndOfWord);
case SentenceBoundary: {
// QCursor does not provide functionality to move to next sentence.
// We therefore find the current block, then go through the block using
// QTextBoundaryFinder and find the sentence the \offset represents
- cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
- result.first = cursor.position();
- cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
- result.second = cursor.position();
+ std::pair<int, int> result = qAccessibleTextBoundaryHelperHelper(
+ cursor, QTextCursor::StartOfBlock, QTextCursor::EndOfBlock);
QString blockText = cursor.selectedText();
const int offsetWithinBlockText = offsetCursor.position() - result.first;
QTextBoundaryFinder sentenceFinder(QTextBoundaryFinder::Sentence, blockText);
@@ -1018,25 +1021,19 @@ std::pair< int, int > QAccessible::qAccessibleTextBoundaryHelper(const QTextCurs
result.second = result.first + nextBoundary;
if (prevBoundary != -1)
result.first += prevBoundary;
- break; }
+ return result;
+ }
case LineBoundary:
- cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::MoveAnchor);
- result.first = cursor.position();
- cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
- result.second = cursor.position();
- break;
+ return qAccessibleTextBoundaryHelperHelper(cursor, QTextCursor::StartOfLine,
+ QTextCursor::EndOfLine);
case ParagraphBoundary:
- cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
- result.first = cursor.position();
- cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
- result.second = cursor.position();
- break;
+ return qAccessibleTextBoundaryHelperHelper(cursor, QTextCursor::StartOfBlock,
+ QTextCursor::EndOfBlock);
case NoBoundary:
- result.first = 0;
- result.second = characterCount;
- break;
+ return qAccessibleTextBoundaryHelperHelper(cursor, QTextCursor::Start, QTextCursor::End);
}
- return result;
+
+ Q_UNREACHABLE_RETURN({});
}
/*!
@@ -2274,13 +2271,16 @@ QString QAccessibleTextInterface::textBeforeOffset(int offset, QAccessible::Text
break;
} while (boundary.toPreviousBoundary() > 0);
Q_ASSERT(boundary.position() >= 0);
- *endOffset = boundary.position();
+ const int endPos = boundary.position();
while (boundary.toPreviousBoundary() > 0) {
if ((boundary.boundaryReasons() & (QTextBoundaryFinder::StartOfItem | QTextBoundaryFinder::EndOfItem)))
break;
}
- Q_ASSERT(boundary.position() >= 0);
+ if (boundary.position() < 0)
+ return QString();
+
+ *endOffset = endPos;
*startOffset = boundary.position();
return txt.mid(*startOffset, *endOffset - *startOffset);
@@ -2437,13 +2437,17 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun
break;
} while (boundary.toPreviousBoundary() > 0);
Q_ASSERT(boundary.position() >= 0);
- *startOffset = boundary.position();
+ const int startPos = boundary.position();
while (boundary.toNextBoundary() < txt.size()) {
if ((boundary.boundaryReasons() & (QTextBoundaryFinder::StartOfItem | QTextBoundaryFinder::EndOfItem)))
break;
+ if (boundary.position() == -1)
+ return QString();
}
+
Q_ASSERT(boundary.position() <= txt.size());
+ *startOffset = startPos;
*endOffset = boundary.position();
return txt.mid(*startOffset, *endOffset - *startOffset);
diff --git a/src/gui/accessible/qaccessible_base.h b/src/gui/accessible/qaccessible_base.h
index 31b97880ffc..3881c6346a0 100644
--- a/src/gui/accessible/qaccessible_base.h
+++ b/src/gui/accessible/qaccessible_base.h
@@ -156,8 +156,6 @@ public:
quint64 searchEdit : 1;
- // quint64 horizontal : 1;
- // quint64 vertical : 1;
// quint64 invalidEntry : 1;
// quint64 managesDescendants : 1;
// quint64 singleLine : 1; // we have multi line, this is redundant.
@@ -380,6 +378,7 @@ public:
Custom,
Level,
Locale,
+ Orientation,
};
Q_ENUM(Attribute)
diff --git a/src/gui/accessible/qaccessiblehelper.cpp b/src/gui/accessible/qaccessiblehelper.cpp
index 2ae8ebbac08..9ea72b1f6c9 100644
--- a/src/gui/accessible/qaccessiblehelper.cpp
+++ b/src/gui/accessible/qaccessiblehelper.cpp
@@ -3,6 +3,8 @@
#include "qaccessiblehelper_p.h"
+#include <QtGui/qtextcursor.h>
+
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
@@ -48,4 +50,79 @@ QString qt_accStripAmp(const QString &text)
return newText.replace("&&"_L1, "&"_L1);
}
+QString qt_accTextBeforeOffsetHelper(const QAccessibleTextInterface &textInterface,
+ const QTextCursor &textCursor, int offset,
+ QAccessible::TextBoundaryType boundaryType, int *startOffset,
+ int *endOffset)
+{
+ Q_ASSERT(startOffset);
+ Q_ASSERT(endOffset);
+ *startOffset = *endOffset = -1;
+
+ QTextCursor cursor = textCursor;
+ cursor.setPosition(offset);
+ std::pair<int, int> boundaries =
+ QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+ if (boundaries.second > offset) {
+ cursor.setPosition(boundaries.first);
+ while (boundaries.second > offset) {
+ if (!cursor.movePosition(QTextCursor::PreviousCharacter))
+ return QString();
+ boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+ }
+ }
+
+ *startOffset = boundaries.first;
+ *endOffset = boundaries.second;
+
+ return textInterface.text(boundaries.first, boundaries.second);
+}
+
+QString qt_accTextAfterOffsetHelper(const QAccessibleTextInterface &textInterface,
+ const QTextCursor &textCursor, int offset,
+ QAccessible::TextBoundaryType boundaryType, int *startOffset,
+ int *endOffset)
+{
+ Q_ASSERT(startOffset);
+ Q_ASSERT(endOffset);
+ *startOffset = *endOffset = -1;
+
+ QTextCursor cursor = textCursor;
+ cursor.setPosition(offset);
+ std::pair<int, int> boundaries =
+ QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+ if (boundaries.first <= offset) {
+ cursor.setPosition(boundaries.second);
+ while (boundaries.first <= offset) {
+ if (!cursor.movePosition(QTextCursor::NextCharacter))
+ return QString();
+ boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+ }
+ }
+
+ *startOffset = boundaries.first;
+ *endOffset = boundaries.second;
+
+ return textInterface.text(boundaries.first, boundaries.second);
+}
+
+QString qt_accTextAtOffsetHelper(const QAccessibleTextInterface &textInterface,
+ const QTextCursor &textCursor, int offset,
+ QAccessible::TextBoundaryType boundaryType, int *startOffset,
+ int *endOffset)
+{
+ Q_ASSERT(startOffset);
+ Q_ASSERT(endOffset);
+
+ QTextCursor cursor = textCursor;
+ cursor.setPosition(offset);
+ std::pair<int, int> boundaries =
+ QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+
+ *startOffset = boundaries.first;
+ *endOffset = boundaries.second;
+
+ return textInterface.text(boundaries.first, boundaries.second);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/accessible/qaccessiblehelper_p.h b/src/gui/accessible/qaccessiblehelper_p.h
index 38cc493fdea..03cccbbe539 100644
--- a/src/gui/accessible/qaccessiblehelper_p.h
+++ b/src/gui/accessible/qaccessiblehelper_p.h
@@ -16,12 +16,30 @@
//
#include <QtCore/QString>
+#include <QtGui/qaccessible.h>
#include <QtGui/qtguiglobal.h>
+class QTextCursor;
+
QT_BEGIN_NAMESPACE
Q_GUI_EXPORT QString qt_accStripAmp(const QString &text);
+Q_GUI_EXPORT QString qt_accTextBeforeOffsetHelper(const QAccessibleTextInterface &textInterface,
+ const QTextCursor &textCursor, int offset,
+ QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset);
+
+Q_GUI_EXPORT QString qt_accTextAfterOffsetHelper(const QAccessibleTextInterface &textInterface,
+ const QTextCursor &textCursor, int offset,
+ QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset);
+
+Q_GUI_EXPORT QString qt_accTextAtOffsetHelper(const QAccessibleTextInterface &textInterface,
+ const QTextCursor &textCursor, int offset,
+ QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset);
+
QT_END_NAMESPACE
#endif // QACCESSIBLEHELPER_P_H
diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake
index ad76bb095a0..5001f2deeec 100644
--- a/src/gui/configure.cmake
+++ b/src/gui/configure.cmake
@@ -1217,17 +1217,6 @@ qt_feature("xcb-egl-plugin" PRIVATE
CONDITION QT_FEATURE_egl AND QT_FEATURE_opengl
EMIT_IF QT_FEATURE_xcb
)
-qt_feature("xcb-native-painting" PRIVATE
- LABEL "Native painting (experimental)"
- AUTODETECT OFF
- CONDITION QT_FEATURE_xcb_xlib AND QT_FEATURE_fontconfig AND XRender_FOUND
- EMIT_IF QT_FEATURE_xcb
-)
-qt_feature("xrender" PRIVATE
- LABEL "XRender for native painting"
- CONDITION QT_FEATURE_xcb_native_painting
- EMIT_IF QT_FEATURE_xcb AND QT_FEATURE_xcb_native_painting
-)
qt_feature("xcb-xlib" PRIVATE
LABEL "XCB Xlib"
CONDITION QT_FEATURE_xlib AND X11_XCB_FOUND
diff --git a/src/gui/doc/src/richtext.qdoc b/src/gui/doc/src/richtext.qdoc
index 2fa49a31e03..f94c436bd80 100644
--- a/src/gui/doc/src/richtext.qdoc
+++ b/src/gui/doc/src/richtext.qdoc
@@ -1047,6 +1047,12 @@
\li \c type (\c 1, \c a, \c A, \c square, \c disc, \c circle)
\endlist
+ Additionally, the following attribute is supported by the \c ol tag:
+
+ \list
+ \li \c start
+ \endlist
+
\section1 Table Cell Attributes
The following attributes are supported by the \c td and \c th
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 6ba113ef8fb..4a8b409379c 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -47,6 +47,9 @@
#include <memory>
+#define QT_XFORM_TYPE_MSBFIRST 0
+#define QT_XFORM_TYPE_LSBFIRST 1
+
QT_BEGIN_NAMESPACE
class QCmyk32;
@@ -4447,6 +4450,8 @@ int QImage::metric(PaintDeviceMetric metric) const
trigx += m11; \
trigy += m12;
// END OF MACRO
+
+static
bool qt_xForm_helper(const QTransform &trueMat, int xoffset, int type, int depth,
uchar *dptr, qsizetype dbpl, int p_inc, int dHeight,
const uchar *sptr, qsizetype sbpl, int sWidth, int sHeight)
diff --git a/src/gui/image/qplatformpixmap.h b/src/gui/image/qplatformpixmap.h
index 5621afa4da5..3346ca85375 100644
--- a/src/gui/image/qplatformpixmap.h
+++ b/src/gui/image/qplatformpixmap.h
@@ -33,7 +33,7 @@ public:
enum ClassId { RasterClass, DirectFBClass,
BlitterClass, Direct2DClass,
- X11Class, CustomClass = 1024 };
+ CustomClass = 1024 };
QPlatformPixmap(PixelType pixelType, int classId);
virtual ~QPlatformPixmap();
@@ -111,7 +111,6 @@ protected:
private:
friend class QPixmap;
- friend class QX11PlatformPixmap;
friend class QImagePixmapCleanupHooks; // Needs to set is_cached
int detach_no;
@@ -122,10 +121,6 @@ private:
uint is_cached;
};
-# define QT_XFORM_TYPE_MSBFIRST 0
-# define QT_XFORM_TYPE_LSBFIRST 1
-Q_GUI_EXPORT bool qt_xForm_helper(const QTransform&, int, int, int, uchar*, qsizetype, int, int, const uchar*, qsizetype, int, int);
-
QT_END_NAMESPACE
#endif // QPLATFORMPIXMAP_H
diff --git a/src/gui/itemmodels/qfilesystemmodel.cpp b/src/gui/itemmodels/qfilesystemmodel.cpp
index 622c2e5bc92..9eb31f1b6d4 100644
--- a/src/gui/itemmodels/qfilesystemmodel.cpp
+++ b/src/gui/itemmodels/qfilesystemmodel.cpp
@@ -1787,14 +1787,17 @@ bool QFileSystemModel::event(QEvent *event)
bool QFileSystemModel::rmdir(const QModelIndex &aindex)
{
+ Q_D(QFileSystemModel);
+
QString path = filePath(aindex);
const bool success = QDir().rmdir(path);
-#if QT_CONFIG(filesystemwatcher)
if (success) {
- QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
+#if QT_CONFIG(filesystemwatcher)
d->fileInfoGatherer->removePath(path);
- }
#endif
+ QFileSystemModelPrivate::QFileSystemNode *parentNode = d->node(aindex.parent());
+ d->removeNode(parentNode, fileName(aindex));
+ }
return success;
}
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index e44d9b1468b..518843ffcbd 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -2626,7 +2626,6 @@ void QGuiApplicationPrivate::processEnterEvent(QWindowSystemInterfacePrivate::En
}
currentMouseWindow = e->enter;
- lastCursorPosition = e->globalPos;
// TODO later: EnterEvent must report _which_ mouse entered the window; for now we assume primaryPointingDevice()
QEnterEvent event(e->localPos, e->localPos, e->globalPos);
@@ -3408,6 +3407,15 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E
return;
QWindowPrivate *p = qt_window_private(window);
+ if (e->isExposed) {
+ // If the window has been automatically positioned or resized by the
+ // window manager, we now assume those have taken effect, even for
+ // asynchronous window managers. From this point on we want the window
+ // to keep its geometry, even when recreated.
+ p->positionAutomatic = false;
+ p->resizeAutomatic = false;
+ }
+
if (!p->receivedExpose) {
if (p->resizeEventPending) {
// as a convenience for plugins, send a resize event before the first expose event if they haven't done so
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index c23be8eb3ad..bad5932c457 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -582,12 +582,6 @@ void QWindowPrivate::create(bool recursive)
platformWindow->initialize();
- // Now that the window is created and initialized the platform has had
- // a chance to position and size it automatically. From this point on
- // we want the window to keep its geometry, even when recreated.
- positionAutomatic = false;
- resizeAutomatic = false;
-
QObjectList childObjects = q->children();
for (int i = 0; i < childObjects.size(); i ++) {
QObject *object = childObjects.at(i);
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 5763696266a..38c4a9ea87f 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -2937,6 +2937,8 @@ qreal QPainterPath::percentAtLength(qreal len) const
if (len > totalLength)
return 1;
+ Q_ASSERT(totalLength != 0);
+
if (d->cacheEnabled) {
const int ei = qMax(d->elementAtT(len / totalLength), 1); // Skip initial MoveTo
qreal res = 0;
@@ -3117,6 +3119,7 @@ QPointF QPainterPath::pointAtPercent(qreal t) const
qreal curLen = 0;
qreal bezierLen = 0;
QBezier b = d_ptr->bezierAtT(*this, t, &curLen, &bezierLen);
+ Q_ASSERT(bezierLen != 0);
qreal realT = (totalLength * t - curLen) / bezierLen;
return b.pointAt(qBound(qreal(0), realT, qreal(1)));
@@ -3141,10 +3144,14 @@ qreal QPainterPath::angleAtPercent(qreal t) const
return 0;
}
+ if (isEmpty())
+ return 0;
+
qreal totalLength = length();
qreal curLen = 0;
qreal bezierLen = 0;
QBezier bez = d_ptr->bezierAtT(*this, t, &curLen, &bezierLen);
+ Q_ASSERT(bezierLen != 0);
qreal realT = (totalLength * t - curLen) / bezierLen;
qreal m1 = slopeAt(realT, bez.x1, bez.x2, bez.x3, bez.x4);
@@ -3170,10 +3177,14 @@ qreal QPainterPath::slopeAtPercent(qreal t) const
return 0;
}
+ if (isEmpty())
+ return 0;
+
qreal totalLength = length();
qreal curLen = 0;
qreal bezierLen = 0;
QBezier bez = d_ptr->bezierAtT(*this, t, &curLen, &bezierLen);
+ Q_ASSERT(bezierLen != 0);
qreal realT = (totalLength * t - curLen) / bezierLen;
qreal m1 = slopeAt(realT, bez.x1, bez.x2, bez.x3, bez.x4);
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index d27539b2419..c9df5d28a45 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -301,6 +301,8 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c,
const QFixedPoint &subPixelPosition)
{
QImage mask = textureMapForGlyph(g, subPixelPosition);
+ if (mask.isNull())
+ return;
#ifdef CACHE_DEBUG
printf("fillTexture of %dx%d at %d,%d in the cache of %dx%d\n", c.w, c.h, c.x, c.y, m_image.width(), m_image.height());
diff --git a/src/gui/platform/darwin/qappleiconengine.mm b/src/gui/platform/darwin/qappleiconengine.mm
index 20d50b0d8a8..3228b97fdb0 100644
--- a/src/gui/platform/darwin/qappleiconengine.mm
+++ b/src/gui/platform/darwin/qappleiconengine.mm
@@ -30,27 +30,28 @@ auto *loadImage(const QString &iconName)
{"call-start"_L1, @"phone.arrow.up.right"},
{"call-stop"_L1, @"phone.down"},
{"contact-new"_L1, @"person.crop.circle.badge.plus"},
- {"document-new"_L1, @"doc.badge.plus"},
- {"document-open"_L1, @"folder"},
- {"document-open-recent"_L1, @"doc.badge.clock"},
- {"document-page-setup"_L1, @"doc.badge.gearshape"},
+ {"document-new"_L1, @"plus"},
+ {"document-open"_L1, @"arrow.up.forward"},
+ {"document-open-recent"_L1, @"clock"},
+ {"document-page-setup"_L1, @"text.page"},
{"document-print"_L1, @"printer"},
- //{"document-print-preview"_L1, @""},
- {"document-properties"_L1, @"doc.badge.ellipsis"},
- //{"document-revert"_L1, @""},
+ {"document-print-preview"_L1, @"richtext.page"},
+ {"document-properties"_L1, @"info.circle.text.page"},
+ {"document-revert"_L1, @"arrow.counterclockwise"},
{"document-save"_L1, @"square.and.arrow.down"},
- //{"document-save-as"_L1, @""},
+ {"document-save-as"_L1, @"square.and.arrow.down.on.square"},
{"document-send"_L1, @"paperplane"},
+ {"document-export"_L1, @"square.and.arrow.up"},
{"edit-clear"_L1, @"xmark.circle"},
{"edit-copy"_L1, @"doc.on.doc"},
{"edit-cut"_L1, @"scissors"},
- {"edit-delete"_L1, @"delete.left"},
- {"edit-find"_L1, @"magnifyingglass"},
+ {"edit-delete"_L1, @"trash"},
+ {"edit-find"_L1, @"text.page.badge.magnifyingglass"},
//{"edit-find-replace"_L1, @"arrow.up.left.and.down.right.magnifyingglass"},
- {"edit-paste"_L1, @"clipboard"},
- {"edit-redo"_L1, @"arrowshape.turn.up.right"},
- //{"edit-select-all"_L1, @""},
- {"edit-undo"_L1, @"arrowshape.turn.up.left"},
+ {"edit-paste"_L1, @"document.on.clipboard"},
+ {"edit-redo"_L1, @"arrow.uturn.forward"},
+ {"edit-select-all"_L1, @"character.textbox"},
+ {"edit-undo"_L1, @"arrow.uturn.backward"},
{"folder-new"_L1, @"folder.badge.plus"},
{"format-indent-less"_L1, @"decrease.indent"},
{"format-indent-more"_L1, @"increase.indent"},
@@ -65,35 +66,36 @@ auto *loadImage(const QString &iconName)
{"format-text-underline"_L1, @"underline"},
{"format-text-strikethrough"_L1, @"strikethrough"},
//{"go-bottom"_L1, @""},
- {"go-down"_L1, @"arrowshape.down"},
- {"go-first"_L1, @"increase.indent"},
+ {"go-down"_L1, @"chevron.down"},
+ //{"go-first"_L1, @""},
{"go-home"_L1, @"house"},
//{"go-jump"_L1, @""},
//{"go-last"_L1, @""},
- {"go-next"_L1, @"arrowshape.right"},
- {"go-previous"_L1, @"arrowshape.left"},
+ {"go-next"_L1, @"chevron.right"},
+ {"go-previous"_L1, @"chevron.left"},
//{"go-top"_L1, @""},
- {"go-up"_L1, @"arrowshape.up"},
+ {"go-up"_L1, @"chevron.up"},
{"help-about"_L1, @"info.circle"},
//{"help-contents"_L1, @""},
{"help-faq"_L1, @"questionmark.app"},
{"insert-image"_L1, @"photo.badge.plus"},
{"insert-link"_L1, @"link.badge.plus"},
- //{"insert-object"_L1, @""},
- {"insert-text"_L1, @"textformat"},
+ {"insert-object"_L1, @"widget.small.badge.plus"},
+ {"insert-text"_L1, @"text.badge.plus"},
{"list-add"_L1, @"plus.circle"},
{"list-remove"_L1, @"minus.circle"},
{"mail-forward"_L1, @"arrowshape.turn.up.right"},
{"mail-mark-important"_L1, @"star"},
{"mail-mark-junk"_L1, @"xmark.bin"},
- {"mail-mark-notjunk"_L1, @"trash.slash"},
+ {"mail-mark-notjunk"_L1, @"arrow.up.bin"},
{"mail-mark-read"_L1, @"envelope.open"},
- {"mail-mark-unread"_L1, @"envelope.fill"},
+ {"mail-mark-unread"_L1, @"envelope.badge"},
{"mail-message-new"_L1, @"square.and.pencil"},
{"mail-reply-all"_L1, @"arrowshape.turn.up.left.2"},
{"mail-reply-sender"_L1, @"arrowshape.turn.up.left"},
- {"mail-send"_L1, @"paperplane"},
- {"mail-send-receive"_L1, @"envelope.arrow.triangle.branch"},
+ {"mail-send"_L1, @"arrow.up.circle.fill"},
+ {"mail-send-receive"_L1, @"arrow.trianglehead.2.clockwise.rotate.90"},
+ {"mail-replied"_L1, @"envelope.and.arrow.trianglehead.branch"},
{"media-eject"_L1, @"eject"},
{"media-playback-pause"_L1, @"pause"},
{"media-playback-start"_L1, @"play"},
@@ -108,61 +110,61 @@ auto *loadImage(const QString &iconName)
{"object-rotate-left"_L1, @"rotate.left"},
{"object-rotate-right"_L1, @"rotate.right"},
{"process-stop"_L1, @"stop.circle"},
- {"system-lock-screen"_L1, @"lock.display"},
- {"system-log-out"_L1, @"door.left.hand.open"},
+ {"system-lock-screen"_L1, @"lock"},
+ {"system-log-out"_L1, @"person.crop.circle"},
//{"system-run"_L1, @""},
{"system-search"_L1, @"magnifyingglass"},
- //{"system-reboot"_L1, @""},
+ {"system-reboot"_L1, @"restart"},
{"system-shutdown"_L1, @"power"},
- //{"tools-check-spelling"_L1, @""},
+ {"tools-check-spelling"_L1, @"textformat.characters.dottedunderline"},
{"view-fullscreen"_L1, @"arrow.up.left.and.arrow.down.right"},
{"view-refresh"_L1, @"arrow.clockwise"},
{"view-restore"_L1, @"arrow.down.right.and.arrow.up.left"},
- //{"view-sort-ascending"_L1, @""},
- //{"view-sort-descending"_L1, @""},
+ {"view-sort-ascending"_L1, @"arrow.up"},
+ {"view-sort-descending"_L1, @"arrow.down"},
{"window-close"_L1, @"xmark.circle"},
{"window-new"_L1, @"macwindow.badge.plus"},
{"zoom-fit-best"_L1, @"square.arrowtriangle.4.outward"},
{"zoom-in"_L1, @"plus.magnifyingglass"},
- //{"zoom-original"_L1, @""},
+ {"zoom-original"_L1, @"1.magnifyingglass"},
{"zoom-out"_L1, @"minus.magnifyingglass"},
{"process-working"_L1, @"circle.dotted"},
- //{"accessories-calculator"_L1, @""},
- //{"accessories-character-map"_L1, @""},
+ {"accessories-calculator"_L1, @"plus.forwardslash.minus"},
+ {"accessories-character-map"_L1, @"keyboard.macwindow"},
{"accessories-dictionary"_L1, @"character.book.closed"},
{"accessories-text-editor"_L1, @"textformat"},
{"help-browser"_L1, @"folder.badge.questionmark"},
{"multimedia-volume-control"_L1, @"speaker.wave.3"},
{"preferences-desktop-accessibility"_L1, @"accessibility"},
- //{"preferences-desktop-font"_L1, @""},
- {"preferences-desktop-keyboard"_L1, @"keyboard.badge.ellipsis"},
- //{"preferences-desktop-locale"_L1, @""},
- //{"preferences-desktop-multimedia"_L1, @""},
- //{"preferences-desktop-screensaver"_L1, @""},
- //{"preferences-desktop-theme"_L1, @""},
- //{"preferences-desktop-wallpaper"_L1, @""},
+ {"preferences-desktop-font"_L1, @"textformat.characters"},
+ {"preferences-desktop-keyboard"_L1, @"keyboard"},
+ {"preferences-desktop-locale"_L1, @"mappin.and.ellipse"},
+ {"preferences-desktop-multimedia"_L1, @"music.note.tv"},
+ {"preferences-desktop-screensaver"_L1, @"display"},
+ {"preferences-desktop-theme"_L1, @"paintpalette"},
+ {"preferences-desktop-wallpaper"_L1, @"photo.tv"},
{"system-file-manager"_L1, @"folder.badge.gearshape"},
- //{"system-software-install"_L1, @""},
- //{"system-software-update"_L1, @""}, d
- //{"utilities-system-monitor"_L1, @""},
+ {"system-software-install"_L1, @"laptopcomputer.and.arrow.down"},
+ {"system-software-update"_L1, @"laptopcomputer.badge.checkmark"},
+ {"utilities-system-monitor"_L1, @"chart.bar.xaxis"},
{"utilities-terminal"_L1, @"apple.terminal"},
- //{"applications-accessories"_L1, @""},
- //{"applications-development"_L1, @""},
- //{"applications-engineering"_L1, @""},
- {"applications-games"_L1, @"gamecontroller"},
- //{"applications-graphics"_L1, @""},
+ {"applications-accessories"_L1, @"scanner"},
+ {"applications-development"_L1, @"hammer"},
+ {"applications-engineering"_L1, @"wrench.and.screwdriver"},
+ {"applications-games"_L1, @"gamecontroller.circle"},
+ {"applications-graphics"_L1, @"theatermask.and.paintbrush"},
{"applications-internet"_L1, @"network"},
{"applications-multimedia"_L1, @"tv.and.mediabox"},
- //{"applications-office"_L1, @""},
- //{"applications-other"_L1, @""},
+ {"applications-office"_L1, @"square.and.pencil.circle"},
+ {"applications-other"_L1, @"app.grid"},
{"applications-science"_L1, @"atom"},
- //{"applications-system"_L1, @""},
- //{"applications-utilities"_L1, @""},
+ {"applications-system"_L1, @"gear"},
+ {"applications-utilities"_L1, @"wrench.and.screwdriver"},
{"preferences-desktop"_L1, @"menubar.dock.rectangle"},
- //{"preferences-desktop-peripherals"_L1, @""},
- //{"preferences-desktop-personal"_L1, @""},
- //{"preferences-other"_L1, @""},
- //{"preferences-system"_L1, @""},
+ {"preferences-desktop-peripherals"_L1, @"iphone.and.ipod"},
+ {"preferences-desktop-personal"_L1, @"person.badge.key"},
+ {"preferences-other"_L1, @"gear"},
+ {"preferences-system"_L1, @"gear"},
{"preferences-system-network"_L1, @"network"},
{"system-help"_L1, @"questionmark.diamond"},
{"audio-card"_L1, @"waveform.circle"},
@@ -175,40 +177,40 @@ auto *loadImage(const QString &iconName)
{"drive-harddisk"_L1, @"internaldrive"},
{"drive-optical"_L1, @"opticaldiscdrive"},
{"drive-removable-media"_L1, @"externaldrive"},
- {"input-gaming"_L1, @"gamecontroller"}, // "games" also using this one
+ {"input-gaming"_L1, @"gamecontroller"},
{"input-keyboard"_L1, @"keyboard"},
{"input-mouse"_L1, @"computermouse"},
{"input-tablet"_L1, @"ipad"},
{"media-flash"_L1, @"mediastick"},
//{"media-floppy"_L1, @""},
- //{"media-optical"_L1, @""},
+ {"media-optical"_L1, @"opticaldisc"},
{"media-tape"_L1, @"recordingtape"},
- //{"modem"_L1, @""},
- {"multimedia-player"_L1, @"play.rectangle"},
+ {"modem"_L1, @"phone.connection"},
+ {"multimedia-player"_L1, @"ipod"},
{"network-wired"_L1, @"app.connected.to.app.below.fill"},
{"network-wireless"_L1, @"wifi"},
{"network-workgroup"_L1, @"network"},
- //{"pda"_L1, @""},
+ {"pda"_L1, @"flipphone"},
{"phone"_L1, @"iphone"},
{"printer"_L1, @"printer"},
{"scanner"_L1, @"scanner"},
{"video-display"_L1, @"play.display"},
- //{"emblem-default"_L1, @""},
+ {"emblem-default"_L1, @"circle"},
{"emblem-documents"_L1, @"doc.circle"},
{"emblem-downloads"_L1, @"arrow.down.circle"},
- {"emblem-favorite"_L1, @"star"},
- {"emblem-important"_L1, @"exclamationmark.bubble.circle"},
- {"emblem-mail"_L1, @"envelope"},
- {"emblem-photos"_L1, @"photo.stack"},
- //{"emblem-readonly"_L1, @""},
- {"emblem-shared"_L1, @"folder.badge.person.crop"},
+ {"emblem-favorite"_L1, @"star.circle"},
+ {"emblem-important"_L1, @"exclamationmark.circle"},
+ {"emblem-mail"_L1, @"envelope.circle"},
+ {"emblem-photos"_L1, @"photo.circle"},
+ {"emblem-readonly"_L1, @"eye.circle"},
+ {"emblem-shared"_L1, @"person.2.circle"},
{"emblem-symbolic-link"_L1, @"link.circle"},
{"emblem-synchronized"_L1, @"arrow.triangle.2.circlepath.circle"},
- {"emblem-system"_L1, @"gear"},
- //{"emblem-unreadable"_L1, @""},
+ {"emblem-system"_L1, @"gear.circle"},
+ {"emblem-unreadable"_L1, @"eye.slash.circle"},
{"text-x-generic"_L1, @"doc"}, // until iOS 18/macOS 15; @"document" after that
{"folder"_L1, @"folder"},
- //{"folder-remote"_L1, @""},
+ {"folder-remote"_L1, @"icloud"},
{"network-server"_L1, @"server.rack"},
//{"start-here"_L1, @""},
{"user-bookmarks"_L1, @"bookmark.circle"},
@@ -229,28 +231,28 @@ auto *loadImage(const QString &iconName)
{"dialog-question"_L1, @"questionmark.circle"},
{"dialog-warning"_L1, @"exclamationmark.octagon"},
{"folder-drag-accept"_L1, @"plus.rectangle.on.folder"},
- //{"folder-open"_L1, @""},
+ {"folder-open"_L1, @"arrow.forward.folder"},
{"folder-visiting"_L1, @"folder.circle"},
- {"image-loading"_L1, @"photo.circle"},
- {"image-missing"_L1, @"photo"},
+ {"image-loading"_L1, @"photo.badge.arrow.down"},
+ {"image-missing"_L1, @"photo.badge.exclamationmark"},
{"mail-attachment"_L1, @"paperclip"},
{"mail-unread"_L1, @"envelope.badge"},
{"mail-read"_L1, @"envelope.open"},
- {"mail-replied"_L1, @"arrowshape.turn.up.left"},
+ //{"mail-replied"_L1, @""},
//{"mail-signed"_L1, @""},
- //{"mail-signed-verified"_L1, @""},
- {"media-playlist-repeat"_L1, @"repet"},
+ {"mail-signed-verified"_L1, @"envelope.badge.shield.half.filled"},
+ {"media-playlist-repeat"_L1, @"repeat"},
{"media-playlist-shuffle"_L1, @"shuffle"},
- //{"network-error"_L1, @""},
- //{"network-idle"_L1, @""},
- {"network-offline"_L1, @"network.slash"},
- //{"network-receive"_L1, @""},
- //{"network-transmit"_L1, @""},
- //{"network-transmit-receive"_L1, @""},
+ {"network-error"_L1, @"xmark.icloud"},
+ {"network-idle"_L1, @"icloud"},
+ {"network-offline"_L1, @"icloud.slash"},
+ {"network-receive"_L1, @"icloud.and.arrow.down"},
+ {"network-transmit"_L1, @"icloud.and.arrow.up"},
+ {"network-transmit-receive"_L1, @"arrow.trianglehead.2.clockwise.rotate.90.icloud"},
//{"printer-error"_L1, @""},
- {"printer-printing"_L1, @"printer.dotmatrix.filled.and.paper"}, // not sure
- {"security-high"_L1, @"lock.shield"},
- //{"security-medium"_L1, @""},
+ {"printer-printing"_L1, @"printer.dotmatrix"},
+ {"security-high"_L1, @"lock.badge.checkmark"},
+ {"security-medium"_L1, @"lock"},
{"security-low"_L1, @"lock.trianglebadge.exclamationmark"},
{"software-update-available"_L1, @"arrowshape.up.circle"},
{"software-update-urgent"_L1, @"exclamationmark.transmission"},
@@ -258,9 +260,9 @@ auto *loadImage(const QString &iconName)
{"sync-synchronizing"_L1, @"arrow.triangle.2.circlepath"},
{"task-due"_L1, @"clock.badge.exclamationmark"},
{"task-past-due"_L1, @"clock.badge.xmark"},
- {"user-available"_L1, @"person.crop.circle.badge.checkmark"},
- {"user-away"_L1, @"person.crop.circle.badge.clock"},
- //{"user-idle"_L1, @""},
+ {"user-available"_L1, @"person.crop.circle.badge"},
+ {"user-away"_L1, @"person.crop.circle.badge.moon"},
+ {"user-idle"_L1, @"person.crop.circle.badge.clock"},
{"user-offline"_L1, @"person.crop.circle.badge.xmark"},
//{"user-trash-full"_L1, @""},
{"weather-clear"_L1, @"sun.max"},
@@ -269,9 +271,9 @@ auto *loadImage(const QString &iconName)
{"weather-few-clouds-night"_L1, @"cloud.moon"},
{"weather-fog"_L1, @"cloud.fog"},
{"weather-overcast"_L1, @"cloud"},
- //{"weather-severe-alert"_L1, @""},
- {"weather-showers"_L1, @"cloud.rain"},
- //{"weather-showers-scattered"_L1, @""},
+ {"weather-severe-alert"_L1, @"cloud.bolt.rain"},
+ {"weather-showers"_L1, @"cloud.heavyrain"},
+ {"weather-showers-scattered"_L1, @"cloud.drizzle"},
{"weather-snow"_L1, @"cloud.snow"},
{"weather-storm"_L1, @"tropicalstorm"},
};
diff --git a/src/gui/platform/darwin/qapplekeymapper.mm b/src/gui/platform/darwin/qapplekeymapper.mm
index 214865864ff..49f7a8ff0cb 100644
--- a/src/gui/platform/darwin/qapplekeymapper.mm
+++ b/src/gui/platform/darwin/qapplekeymapper.mm
@@ -94,60 +94,10 @@ static CarbonModifiers toCarbonModifiers(Qt::KeyboardModifiers qtModifiers)
return carbonModifiers;
}
-// Keyboard keys (non-modifiers)
-static QHash<char16_t, Qt::Key> standardKeys = {
- { kHomeCharCode, Qt::Key_Home },
- { kEnterCharCode, Qt::Key_Enter },
- { kEndCharCode, Qt::Key_End },
- { kBackspaceCharCode, Qt::Key_Backspace },
- { kTabCharCode, Qt::Key_Tab },
- { kPageUpCharCode, Qt::Key_PageUp },
- { kPageDownCharCode, Qt::Key_PageDown },
- { kReturnCharCode, Qt::Key_Return },
- { kEscapeCharCode, Qt::Key_Escape },
- { kLeftArrowCharCode, Qt::Key_Left },
- { kRightArrowCharCode, Qt::Key_Right },
- { kUpArrowCharCode, Qt::Key_Up },
- { kDownArrowCharCode, Qt::Key_Down },
- { kHelpCharCode, Qt::Key_Help },
- { kDeleteCharCode, Qt::Key_Delete },
- // ASCII maps, for debugging
- { ':', Qt::Key_Colon },
- { ';', Qt::Key_Semicolon },
- { '<', Qt::Key_Less },
- { '=', Qt::Key_Equal },
- { '>', Qt::Key_Greater },
- { '?', Qt::Key_Question },
- { '@', Qt::Key_At },
- { ' ', Qt::Key_Space },
- { '!', Qt::Key_Exclam },
- { '"', Qt::Key_QuoteDbl },
- { '#', Qt::Key_NumberSign },
- { '$', Qt::Key_Dollar },
- { '%', Qt::Key_Percent },
- { '&', Qt::Key_Ampersand },
- { '\'', Qt::Key_Apostrophe },
- { '(', Qt::Key_ParenLeft },
- { ')', Qt::Key_ParenRight },
- { '*', Qt::Key_Asterisk },
- { '+', Qt::Key_Plus },
- { ',', Qt::Key_Comma },
- { '-', Qt::Key_Minus },
- { '.', Qt::Key_Period },
- { '/', Qt::Key_Slash },
- { '[', Qt::Key_BracketLeft },
- { ']', Qt::Key_BracketRight },
- { '\\', Qt::Key_Backslash },
- { '_', Qt::Key_Underscore },
- { '`', Qt::Key_QuoteLeft },
- { '{', Qt::Key_BraceLeft },
- { '}', Qt::Key_BraceRight },
- { '|', Qt::Key_Bar },
- { '~', Qt::Key_AsciiTilde },
- { '^', Qt::Key_AsciiCircum }
-};
-
-static QHash<char16_t, Qt::Key> virtualKeys = {
+// NSEvent.keyCode codes for keys that are independent of keyboard layout.
+// Some of these are technically possible to add custom key maps for, but
+// doing so would be unexpected.
+static QHash<char16_t, Qt::Key> layoutIndependentKeyCodes = {
{ kVK_F1, Qt::Key_F1 },
{ kVK_F2, Qt::Key_F2 },
{ kVK_F3, Qt::Key_F3 },
@@ -164,16 +114,57 @@ static QHash<char16_t, Qt::Key> virtualKeys = {
{ kVK_F14, Qt::Key_F14 },
{ kVK_F15, Qt::Key_F15 },
{ kVK_F16, Qt::Key_F16 },
+ { kVK_F17, Qt::Key_F17 },
+ { kVK_F18, Qt::Key_F18 },
+ { kVK_F19, Qt::Key_F19 },
+ { kVK_F20, Qt::Key_F20 },
+
{ kVK_Return, Qt::Key_Return },
{ kVK_Tab, Qt::Key_Tab },
+ { kVK_Space, Qt::Key_Space },
{ kVK_Escape, Qt::Key_Escape },
- { kVK_Help, Qt::Key_Help },
+ { kVK_Delete, Qt::Key_Backspace },
+ { kVK_ForwardDelete, Qt::Key_Delete },
+
+ { kVK_Home, Qt::Key_Home },
+ { kVK_End, Qt::Key_End },
+ { kVK_PageUp, Qt::Key_PageUp },
+ { kVK_PageDown, Qt::Key_PageDown },
+
{ kVK_UpArrow, Qt::Key_Up },
{ kVK_DownArrow, Qt::Key_Down },
{ kVK_LeftArrow, Qt::Key_Left },
{ kVK_RightArrow, Qt::Key_Right },
- { kVK_PageUp, Qt::Key_PageUp },
- { kVK_PageDown, Qt::Key_PageDown }
+
+ { kVK_CapsLock, Qt::Key_CapsLock },
+ { kVK_Shift, Qt::Key_Shift },
+ { kVK_RightShift, Qt::Key_Shift },
+
+#if 0
+ // FIXME: Map these here instead of relying on
+ // custom logic in [QNSView flagsChanged:]
+
+ { kVK_Command, Qt::Key_unknown },
+ { kVK_RightCommand, Qt::Key_unknown },
+ { kVK_Option, Qt::Key_unknown },
+ { kVK_RightOption, Qt::Key_unknown },
+ { kVK_Control, Qt::Key_unknown },
+ { kVK_RightControl, Qt::Key_unknown },
+ { kVK_Function, Qt::Key_unknown },
+#endif
+
+ { kVK_VolumeUp, Qt::Key_VolumeUp },
+ { kVK_VolumeDown, Qt::Key_VolumeDown },
+ { kVK_Mute, Qt::Key_VolumeMute },
+
+#if 0
+ // FIXME: Figure out which Qt::Key this maps to
+ { kVK_ContextualMenu, Qt::Key_unknown },
+#endif
+ { kVK_Help, Qt::Key_Help },
+
+ { kVK_ANSI_KeypadClear, Qt::Key_Clear },
+ { kVK_ANSI_KeypadEnter, Qt::Key_Enter },
};
static QHash<char16_t, Qt::Key> functionKeys = {
@@ -211,41 +202,19 @@ static int toKeyCode(const QChar &key, int virtualKey, int modifiers)
qCDebug(lcQpaKeyMapperKeys, "Mapping key: %d (0x%04x) / vk %d (0x%04x)",
key.unicode(), key.unicode(), virtualKey, virtualKey);
- if (key == char16_t(kClearCharCode) && virtualKey == 0x47)
- return Qt::Key_Clear;
-
- if (key.isDigit()) {
- qCDebug(lcQpaKeyMapperKeys, "Got digit key: %d", key.digitValue());
- return key.digitValue() + Qt::Key_0;
- }
-
- if (key.isLetter()) {
- qCDebug(lcQpaKeyMapperKeys, "Got letter key: %d", (key.toUpper().unicode() - 'A'));
- return (key.toUpper().unicode() - 'A') + Qt::Key_A;
- }
- if (key.isSymbol()) {
- qCDebug(lcQpaKeyMapperKeys, "Got symbol key: %d", (key.unicode()));
- return key.unicode();
- }
-
- if (auto qtKey = standardKeys.value(key.unicode())) {
+ // Check first if we have a virtual key that should be treated as layout
+ // independent. If so, we want to return early without inspecting the key.
+ if (auto qtKey = layoutIndependentKeyCodes.value(virtualKey)) {
+ qCDebug(lcQpaKeyMapperKeys) << "Got" << qtKey << "based on layout independent virtual key";
// To work like Qt for X11 we issue Backtab when Shift + Tab are pressed
if (qtKey == Qt::Key_Tab && (modifiers & Qt::ShiftModifier)) {
- qCDebug(lcQpaKeyMapperKeys, "Got key: Qt::Key_Backtab");
+ qCDebug(lcQpaKeyMapperKeys, "Transformed into Qt::Key_Backtab");
return Qt::Key_Backtab;
}
-
- qCDebug(lcQpaKeyMapperKeys) << "Got" << qtKey;
- return qtKey;
- }
-
- // Last ditch try to match the scan code
- if (auto qtKey = virtualKeys.value(virtualKey)) {
- qCDebug(lcQpaKeyMapperKeys) << "Got scancode" << qtKey;
return qtKey;
}
- // Check if they belong to key codes in private unicode range
+ // Then check if the key is one of the functions keys in the private Unicode range
if (key >= char16_t(NSUpArrowFunctionKey) && key <= char16_t(NSModeSwitchFunctionKey)) {
if (auto qtKey = functionKeys.value(key.unicode())) {
qCDebug(lcQpaKeyMapperKeys) << "Got" << qtKey;
@@ -257,6 +226,20 @@ static int toKeyCode(const QChar &key, int virtualKey, int modifiers)
}
}
+ if (key.isDigit()) {
+ qCDebug(lcQpaKeyMapperKeys, "Got digit key: %d", key.digitValue());
+ return key.digitValue() + Qt::Key_0;
+ }
+
+ if (key.isLetter()) {
+ qCDebug(lcQpaKeyMapperKeys, "Got letter key: %d", (key.toUpper().unicode() - 'A'));
+ return (key.toUpper().unicode() - 'A') + Qt::Key_A;
+ }
+ if (key.isSymbol()) {
+ qCDebug(lcQpaKeyMapperKeys, "Got symbol key: %d", (key.unicode()));
+ return key.unicode();
+ }
+
qCDebug(lcQpaKeyMapperKeys, "Unknown case.. %d[%d] %d", key.unicode(), key.toLatin1(), virtualKey);
return Qt::Key_unknown;
}
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index 15f5cd8f7e8..81d2719117e 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -3959,6 +3959,7 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
break;
case QGles2CommandBuffer::Command::InvalidateFramebuffer:
if (caps.gles && caps.ctxMajor >= 3) {
+ f->glBindFramebuffer(GL_FRAMEBUFFER, cmd.args.invalidateFramebuffer.fbo);
f->glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER,
cmd.args.invalidateFramebuffer.attCount,
cmd.args.invalidateFramebuffer.att);
@@ -4881,6 +4882,7 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
if (mayDiscardDepthStencil) {
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::InvalidateFramebuffer;
+ cmd.args.invalidateFramebuffer.fbo = rtTex->framebuffer;
if (caps.needsDepthStencilCombinedAttach) {
cmd.args.invalidateFramebuffer.attCount = 1;
cmd.args.invalidateFramebuffer.att[0] = GL_DEPTH_STENCIL_ATTACHMENT;
diff --git a/src/gui/rhi/qrhigles2_p.h b/src/gui/rhi/qrhigles2_p.h
index 725e71a3665..ea061f9d218 100644
--- a/src/gui/rhi/qrhigles2_p.h
+++ b/src/gui/rhi/qrhigles2_p.h
@@ -547,6 +547,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
GLbitfield barriers;
} barrier;
struct {
+ GLuint fbo;
int attCount;
GLenum att[3];
} invalidateFramebuffer;
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index b946f8777b6..c5167a6e7de 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -8824,6 +8824,18 @@ bool QVkSwapChain::ensureSurface()
if (ok) {
colorFormat = formats[i].format;
colorSpace = formats[i].colorSpace;
+#if QT_CONFIG(wayland)
+ // On Wayland, only one color management surface can be created at a time without
+ // triggering a protocol error, and we create one ourselves in some situations.
+ // To avoid this problem, use VK_COLOR_SPACE_PASS_THROUGH_EXT when supported,
+ // so that the driver doesn't create a color management surface as well.
+ const bool hasPassThrough = std::any_of(formats.begin(), formats.end(), [this](const VkSurfaceFormatKHR &fmt) {
+ return fmt.format == colorFormat && fmt.colorSpace == VK_COLOR_SPACE_PASS_THROUGH_EXT;
+ });
+ if (hasPassThrough) {
+ colorSpace = VK_COLOR_SPACE_PASS_THROUGH_EXT;
+ }
+#endif
break;
}
}
diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h
index d1509e4a251..75550439521 100644
--- a/src/gui/text/qfont_p.h
+++ b/src/gui/text/qfont_p.h
@@ -166,6 +166,7 @@ public:
QFontPrivate();
QFontPrivate(const QFontPrivate &other);
+ QFontPrivate &operator=(const QFontPrivate &) = delete;
~QFontPrivate();
QFontEngine *engineForScript(int script) const;
@@ -206,9 +207,6 @@ public:
void setVariableAxis(QFont::Tag tag, float value);
void unsetVariableAxis(QFont::Tag tag);
bool hasVariableAxis(QFont::Tag tag, float value) const;
-
-private:
- QFontPrivate &operator=(const QFontPrivate &) { return *this; }
};
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 11c79f23d25..29fda652ef6 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:critical reason:data-parser
+#include <QtCore/private/qflatmap_p.h>
#include <QtGui/private/qtguiglobal_p.h>
#include "qdebug.h"
#include "qtextformat.h"
@@ -1613,11 +1614,15 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st
{
uint glyphs_shaped = 0;
- hb_buffer_t *buffer = hb_buffer_create();
- hb_buffer_set_unicode_funcs(buffer, hb_qt_get_unicode_funcs());
+ if (!buffer) {
+ buffer = hb_buffer_create();
+ hb_buffer_set_unicode_funcs(buffer, hb_qt_get_unicode_funcs());
+ }
+
hb_buffer_pre_allocate(buffer, itemLength);
if (Q_UNLIKELY(!hb_buffer_allocation_successful(buffer))) {
hb_buffer_destroy(buffer);
+ buffer = nullptr;
return 0;
}
@@ -1671,26 +1676,26 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st
bool dontLigate = hasLetterSpacing && !scriptRequiresOpenType;
- QHash<QFont::Tag, quint32> features;
- features.insert(QFont::Tag("kern"), !!kerningEnabled);
+ QVarLengthFlatMap<QFont::Tag, hb_feature_t, 16> features;
+ auto insertFeature = [&features](QFont::Tag tag, quint32 value) {
+ features.insert(tag, { tag.value(),
+ value,
+ HB_FEATURE_GLOBAL_START,
+ HB_FEATURE_GLOBAL_END });
+ };
+ // fontFeatures have precedence
+ for (const auto &[tag, value]: fontFeatures.asKeyValueRange())
+ insertFeature(tag, value);
+ insertFeature(QFont::Tag("kern"), !!kerningEnabled);
if (dontLigate) {
- features.insert(QFont::Tag("liga"), false);
- features.insert(QFont::Tag("clig"), false);
- features.insert(QFont::Tag("dlig"), false);
- features.insert(QFont::Tag("hlig"), false);
- }
- features.insert(fontFeatures);
-
- QVarLengthArray<hb_feature_t, 16> featureArray;
- for (auto it = features.constBegin(); it != features.constEnd(); ++it) {
- featureArray.append({ it.key().value(),
- it.value(),
- HB_FEATURE_GLOBAL_START,
- HB_FEATURE_GLOBAL_END });
+ insertFeature(QFont::Tag("liga"), false);
+ insertFeature(QFont::Tag("clig"), false);
+ insertFeature(QFont::Tag("dlig"), false);
+ insertFeature(QFont::Tag("hlig"), false);
}
// whitelist cross-platforms shapers only
- static const char *shaper_list[] = {
+ constexpr const char *shaper_list[] = {
"graphite2",
"ot",
"fallback",
@@ -1699,13 +1704,11 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st
bool shapedOk = hb_shape_full(hb_font,
buffer,
- featureArray.constData(),
- features.size(),
+ features.values().constData(),
+ features.values().size(),
shaper_list);
- if (Q_UNLIKELY(!shapedOk)) {
- hb_buffer_destroy(buffer);
+ if (Q_UNLIKELY(!shapedOk))
return 0;
- }
if (Q_UNLIKELY(HB_DIRECTION_IS_BACKWARD(props.direction)))
hb_buffer_reverse(buffer);
@@ -1718,10 +1721,8 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st
num_glyphs = 1;
// ensure we have enough space for shaped glyphs and metrics
- if (Q_UNLIKELY(!ensureSpace(glyphs_shaped + num_glyphs))) {
- hb_buffer_destroy(buffer);
+ if (Q_UNLIKELY(!ensureSpace(glyphs_shaped + num_glyphs)))
return 0;
- }
// fetch the shaped glyphs and metrics
QGlyphLayout g = availableGlyphs(&si).mid(glyphs_shaped, num_glyphs);
@@ -1781,8 +1782,6 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st
glyphs_shaped += num_glyphs;
}
- hb_buffer_destroy(buffer);
-
return glyphs_shaped;
}
@@ -1826,6 +1825,12 @@ QTextEngine::~QTextEngine()
delete layoutData;
delete specialData;
resetFontEngineCache();
+#if QT_CONFIG(harfbuzz)
+ if (buffer) {
+ hb_buffer_destroy(buffer);
+ buffer = nullptr;
+ }
+#endif
}
const QCharAttributes *QTextEngine::attributes() const
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index dffbc129b3a..e513fd598ba 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -40,6 +40,8 @@
#include <stdlib.h>
#include <vector>
+struct hb_buffer_t;
+
QT_BEGIN_NAMESPACE
class QFontPrivate;
@@ -583,6 +585,8 @@ private:
void indexFormats();
void resolveFormats() const;
+ mutable hb_buffer_t *buffer = nullptr;
+
public:
bool atWordSeparator(int position) const;
diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp
index a1457006888..1e52e460d38 100644
--- a/src/gui/vulkan/qvulkanwindow.cpp
+++ b/src/gui/vulkan/qvulkanwindow.cpp
@@ -871,6 +871,19 @@ void QVulkanWindowPrivate::init()
}
}
+#if QT_CONFIG(wayland)
+ // On Wayland, only one color management surface can be created at a time without
+ // triggering a protocol error, and we create one ourselves in some situations.
+ // To avoid this problem, use VK_COLOR_SPACE_PASS_THROUGH_EXT when supported,
+ // so that the driver doesn't create a color management surface as well.
+ const bool hasPassthrough = std::any_of(formats.cbegin(), formats.cend(), [this](const VkSurfaceFormatKHR &format) {
+ return format.format == colorFormat && format.colorSpace == VK_COLOR_SPACE_PASS_THROUGH_EXT;
+ });
+ if (hasPassthrough) {
+ colorSpace = VK_COLOR_SPACE_PASS_THROUGH_EXT;
+ }
+#endif
+
const VkFormat dsFormatCandidates[] = {
VK_FORMAT_D24_UNORM_S8_UINT,
VK_FORMAT_D32_SFLOAT_S8_UINT,