Merge "Merge remote-tracking branch 'origin/5.12' into 5.13"

This commit is contained in:
Liang Qi 2019-08-12 13:23:11 +02:00
commit 41f77a6179
33 changed files with 369 additions and 184 deletions

View File

@ -1 +1,2 @@
SOURCES = arch.cpp
include(write_info.pri)

View File

@ -1,2 +1,3 @@
option(host_build)
SOURCES = arch.cpp
include(write_info.pri)

View File

@ -0,0 +1,17 @@
targetinfofile = $$basename(_PRO_FILE_)
targetinfofile ~= s/pro$/target.txt/
win32 {
ext = .exe
} else:android {
file_prefix = lib
ext = .so
} else:wasm {
equals(WASM_OBJECT_FILES, 1): \
ext = .o
else: \
ext = .wasm
}
content = $${file_prefix}$${TARGET}$${ext}
write_file($$OUT_PWD/$$targetinfofile, content)

View File

@ -286,37 +286,13 @@ defineTest(qtConfTest_architecture) {
!qtConfTest_compile($${1}): \
error("Could not determine $$eval($${1}.label). See config.log for details.")
host = $$eval($${1}.host)
isEmpty(host): host = false
file_prefix =
exts = -
$$host {
equals(QMAKE_HOST.os, Windows): \
exts = .exe
} else {
win32 {
exts = .exe
} else:android {
file_prefix = lib
exts = .so
} else:wasm {
exts = .wasm .o
}
}
test = $$eval($${1}.test)
output = $$eval($${1}.output)
test_out_dir = $$OUT_PWD/$$basename(QMAKE_CONFIG_TESTS_DIR)/$$test
test_out_file =
for(ext, exts) {
equals(ext, -): ext =
f = $$test_out_dir/$$file_prefix$$output$$ext
exists($$f) {
test_out_file = $$f
break()
}
}
isEmpty(test_out_file): \
test_out_file = $$test_out_dir/$$cat($$test_out_dir/$${output}.target.txt)
exists($$test_out_file): \
content = $$cat($$test_out_file, blob)
else: \
error("$$eval($${1}.label) detection binary not found.")
content = $$cat($$test_out_file, blob)

View File

@ -1,5 +1,9 @@
load(default_post)
# Recompute SDK version in case the user set it explicitly
sdk_version = $$QMAKE_MAC_SDK_VERSION
QMAKE_MAC_SDK_VERSION = $$xcodeSDKInfo(SDKVersion)
contains(TEMPLATE, .*app) {
!macx-xcode:if(isEmpty(BUILDS)|build_pass) {
# Detect changes to the platform SDK
@ -14,7 +18,7 @@ contains(TEMPLATE, .*app) {
!versionAtLeast(QMAKE_MAC_SDK_VERSION, $$QT_MAC_SDK_VERSION_MIN): \
warning("Qt requires at least version $$QT_MAC_SDK_VERSION_MIN of the platform SDK," \
"you're using $${QMAKE_MAC_SDK_VERSION}. Please upgrade.")
"you're building against version $${QMAKE_MAC_SDK_VERSION}. Please upgrade.")
!isEmpty(QT_MAC_SDK_VERSION_MAX) {
# For Qt developers only
@ -244,6 +248,11 @@ macx-xcode {
QMAKE_PCH_OUTPUT_EXT = _${QMAKE_PCH_ARCH}$${QMAKE_PCH_OUTPUT_EXT}
}
!equals(sdk_version, $$QMAKE_MAC_SDK_VERSION) {
# Explicit SDK version has been set, respect that
QMAKE_LFLAGS += -Wl,-sdk_version -Wl,$$sdk_version
}
cache(QMAKE_XCODE_DEVELOPER_PATH, stash)
!isEmpty(QMAKE_XCODE_VERSION): \
cache(QMAKE_XCODE_VERSION, stash)

View File

@ -2583,10 +2583,8 @@
\section1 RC_FILE
Specifies the name of the resource file for the application.
The value of this variable is typically handled by
qmake or \l{#QMAKESPEC}{qmake.conf} and rarely
needs to be modified.
Windows only. Specifies the name of the Windows resource file (.rc) for the
target. See \l{Adding Windows Resource Files}.
\target RC_CODEPAGE
\section1 RC_CODEPAGE
@ -2649,7 +2647,9 @@
\section1 RES_FILE
Specifies the name of the compiled Windows resource file for the target.
Windows only. Specifies the name of the Windows resource compiler's output
file for this target. See \l{RC_FILE} and \l{Adding Windows Resource Files}.
The value of this variable is typically handled by
qmake or \l{#QMAKESPEC}{qmake.conf} and rarely
needs to be modified.

View File

@ -174,9 +174,9 @@ class Q_CORE_EXPORT QJsonValueRef
{
public:
QJsonValueRef(QJsonArray *array, int idx)
: a(array), is_object(false), index(idx) {}
: a(array), is_object(false), index(static_cast<uint>(idx)) {}
QJsonValueRef(QJsonObject *object, int idx)
: o(object), is_object(true), index(idx) {}
: o(object), is_object(true), index(static_cast<uint>(idx)) {}
inline operator QJsonValue() const { return toValue(); }
QJsonValueRef &operator = (const QJsonValue &val);

View File

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Copyright (C) 2019 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@ -132,12 +132,12 @@ QT_BEGIN_NAMESPACE
* We overallocate the byte array by 1 byte. The first user bit is at
* d.data()[1]. On the extra first byte, we store the difference between the
* number of bits in the byte array (including this byte) and the number of
* bits in the bit array. Therefore, it's always a number between 8 and 15.
* bits in the bit array. Therefore, for a non-empty QBitArray, it's always a
* number between 8 and 15. For the empty one, d is the an empty QByteArray and
* *d.constData() is the QByteArray's terminating NUL (0) byte.
*
* This allows for fast calculation of the bit array size:
* inline int size() const { return (d.size() << 3) - *d.constData(); }
*
* Note: for an array of zero size, *d.constData() is the QByteArray implicit NUL.
*/
/*!
@ -326,6 +326,8 @@ void QBitArray::fill(bool value, int begin, int end)
QBitArray QBitArray::fromBits(const char *data, qsizetype size)
{
QBitArray result;
if (size == 0)
return result;
qsizetype nbytes = (size + 7) / 8;
result.d = QByteArray(nbytes + 1, Qt::Uninitialized);
@ -334,7 +336,7 @@ QBitArray QBitArray::fromBits(const char *data, qsizetype size)
// clear any unused bits from the last byte
if (size & 7)
bits[nbytes] &= 0xffU >> (size & 7);
bits[nbytes] &= 0xffU >> (8 - (size & 7));
*bits = result.d.size() * 8 - size;
return result;

View File

@ -387,19 +387,19 @@ void QCryptographicHash::addData(const char *data, int length)
break;
case RealSha3_224:
case Keccak_224:
sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8);
sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8);
break;
case RealSha3_256:
case Keccak_256:
sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8);
sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8);
break;
case RealSha3_384:
case Keccak_384:
sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8);
sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8);
break;
case RealSha3_512:
case Keccak_512:
sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8);
sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), quint64(length) * 8);
break;
#endif
}

View File

@ -456,6 +456,8 @@ QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QPlatformS
{
if (!m_active)
return { qreal(1), QPoint() };
if (!platformScreen)
return { m_factor, QPoint() }; // the global factor
const QPlatformScreen *actualScreen = nativePosition ?
platformScreen->screenForPosition(*nativePosition) : platformScreen;
return { m_factor * screenSubfactor(actualScreen), actualScreen->geometry().topLeft() };

View File

@ -2908,19 +2908,34 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
for (int i = 0; i < numGlyphs; i++) {
QFixed spp = fontEngine->subPixelPositionForX(positions[i].x);
QPoint offset;
const QImage *alphaMap = fontEngine->lockedAlphaMapForGlyph(glyphs[i], spp, neededFormat, s->matrix,
&offset);
if (alphaMap == 0 || alphaMap->isNull())
const QFontEngine::Glyph *alphaMap = fontEngine->glyphData(glyphs[i], spp, neededFormat, s->matrix);
if (!alphaMap)
continue;
alphaPenBlt(alphaMap->constBits(), alphaMap->bytesPerLine(), alphaMap->depth(),
qFloor(positions[i].x) + offset.x(),
qRound(positions[i].y) + offset.y(),
alphaMap->width(), alphaMap->height(),
fontEngine->expectsGammaCorrectedBlending());
int depth;
int bytesPerLine;
switch (alphaMap->format) {
case QFontEngine::Format_Mono:
depth = 1;
bytesPerLine = ((alphaMap->width + 31) & ~31) >> 3;
break;
case QFontEngine::Format_A8:
depth = 8;
bytesPerLine = (alphaMap->width + 3) & ~3;
break;
case QFontEngine::Format_A32:
depth = 32;
bytesPerLine = alphaMap->width * 4;
break;
default:
Q_UNREACHABLE();
};
fontEngine->unlockAlphaMapForGlyph();
alphaPenBlt(alphaMap->data, bytesPerLine, depth,
qFloor(positions[i].x) + alphaMap->x,
qRound(positions[i].y) - alphaMap->y,
alphaMap->width, alphaMap->height,
fontEngine->expectsGammaCorrectedBlending());
}
} else {

View File

@ -0,0 +1,26 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of Adobe Systems Incorporated nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -923,29 +923,10 @@ QFixed QFontEngine::subPixelPositionForX(QFixed x) const
return subPixelPosition;
}
QImage *QFontEngine::lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition,
QFontEngine::GlyphFormat neededFormat,
const QTransform &t, QPoint *offset)
QFontEngine::Glyph *QFontEngine::glyphData(glyph_t, QFixed,
QFontEngine::GlyphFormat, const QTransform &)
{
Q_ASSERT(currentlyLockedAlphaMap.isNull());
if (neededFormat == Format_None)
neededFormat = Format_A32;
if (neededFormat != Format_A32)
currentlyLockedAlphaMap = alphaMapForGlyph(glyph, subPixelPosition, t);
else
currentlyLockedAlphaMap = alphaRGBMapForGlyph(glyph, subPixelPosition, t);
if (offset != 0)
*offset = QPoint(0, 0);
return &currentlyLockedAlphaMap;
}
void QFontEngine::unlockAlphaMapForGlyph()
{
Q_ASSERT(!currentlyLockedAlphaMap.isNull());
currentlyLockedAlphaMap = QImage();
return nullptr;
}
QImage QFontEngine::alphaMapForGlyph(glyph_t glyph)

View File

@ -124,6 +124,22 @@ public:
};
Q_DECLARE_FLAGS(ShaperFlags, ShaperFlag)
/* Used with the Freetype font engine. We don't cache glyphs that are too large anyway, so we can make this struct rather small */
struct Glyph {
Glyph() = default;
~Glyph() { delete [] data; }
short linearAdvance = 0;
unsigned char width = 0;
unsigned char height = 0;
short x = 0;
short y = 0;
short advance = 0;
signed char format = 0;
uchar *data = nullptr;
private:
Q_DISABLE_COPY(Glyph);
};
virtual ~QFontEngine();
inline Type type() const { return m_type; }
@ -191,11 +207,7 @@ public:
virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
virtual QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color = QColor());
virtual QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition,
GlyphFormat neededFormat,
const QTransform &t = QTransform(),
QPoint *offset = 0);
virtual void unlockAlphaMapForGlyph();
virtual Glyph *glyphData(glyph_t glyph, QFixed subPixelPosition, GlyphFormat neededFormat, const QTransform &t);
virtual bool hasInternalCaching() const { return false; }
virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed /*subPixelPosition*/, const QTransform &matrix, GlyphFormat /*format*/)
@ -346,7 +358,6 @@ public:
void loadKerningPairs(QFixed scalingFactor);
GlyphFormat glyphFormat;
QImage currentlyLockedAlphaMap;
int m_subPixelPositionCount; // Number of positions within a single pixel for this cache
inline QVariant userData() const { return m_userData; }

View File

@ -0,0 +1,17 @@
[
{
"Id": "aglfn",
"Name": "Adobe Glyph List For New Fonts",
"QDocModule": "qtgui",
"Description": "Provides standardized names for glyphs.",
"QtUsage": "Used by PDF generator to make it easier for reader applications to resolve the original contents of rendered text.",
"Path": "qfontsubset_agl.cpp",
"Homepage": "https://github.com/adobe-type-tools/agl-aglfn",
"Version": "1.7",
"License": "BSD 3-Clause \"New\" or \"Revised\" License",
"LicenseId": "BSD-3-Clause",
"LicenseFile": "AGLFN_LICENSE.txt",
"Copyright": "Copyright 2002, 2003, 2005, 2006, 2008, 2010, 2015 Adobe Systems"
}
]

View File

@ -1103,12 +1103,11 @@ void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToCle
bool redoCommandsAvailable = undoState != undoStack.size();
if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) {
for (int i = 0; i < undoState; ++i) {
QTextUndoCommand c = undoStack.at(undoState);
QTextUndoCommand c = undoStack.at(i);
if (c.command & QTextUndoCommand::Custom)
delete c.custom;
}
undoStack.remove(0, undoState);
undoStack.resize(undoStack.size() - undoState);
undoState = 0;
if (emitSignals)
emitUndoAvailable(false);

View File

@ -106,7 +106,7 @@ static bool ft_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *leng
return result;
}
static QFontEngineFT::Glyph emptyGlyph = {0, 0, 0, 0, 0, 0, 0, 0};
static QFontEngineFT::Glyph emptyGlyph;
static const QFontEngine::HintStyle ftInitialDefaultHintStyle =
#ifdef Q_OS_WIN
@ -556,11 +556,6 @@ void QFreetypeFace::addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point,
slot->bitmap.buffer, slot->bitmap.pitch, slot->bitmap.width, slot->bitmap.rows, path);
}
QFontEngineFT::Glyph::~Glyph()
{
delete [] data;
}
struct LcdFilterDummy
{
static inline void filterPixel(uchar &, uchar &, uchar &)
@ -1986,11 +1981,10 @@ static inline QImage alphaMapFromGlyphData(QFontEngineFT::Glyph *glyph, QFontEng
return img;
}
QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixelPosition,
QFontEngine::GlyphFormat neededFormat,
const QTransform &t, QPoint *offset)
QFontEngine::Glyph *QFontEngineFT::glyphData(glyph_t glyphIndex, QFixed subPixelPosition,
QFontEngine::GlyphFormat neededFormat, const QTransform &t)
{
Q_ASSERT(currentlyLockedAlphaMap.isNull());
Q_ASSERT(cacheEnabled);
if (isBitmapFont())
neededFormat = Format_Mono;
@ -2000,33 +1994,10 @@ QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixe
neededFormat = Format_A8;
Glyph *glyph = loadGlyphFor(glyphIndex, subPixelPosition, neededFormat, t);
if (offset != 0 && glyph != 0)
*offset = QPoint(glyph->x, -glyph->y);
currentlyLockedAlphaMap = alphaMapFromGlyphData(glyph, neededFormat);
const bool glyphHasGeometry = glyph != nullptr && glyph->height != 0 && glyph->width != 0;
if (!cacheEnabled && glyph != &emptyGlyph) {
currentlyLockedAlphaMap = currentlyLockedAlphaMap.copy();
delete glyph;
}
if (!glyphHasGeometry)
if (!glyph || !glyph->width || !glyph->height)
return nullptr;
if (currentlyLockedAlphaMap.isNull())
return QFontEngine::lockedAlphaMapForGlyph(glyphIndex, subPixelPosition, neededFormat, t, offset);
QImageData *data = currentlyLockedAlphaMap.data_ptr();
data->is_locked = true;
return &currentlyLockedAlphaMap;
}
void QFontEngineFT::unlockAlphaMapForGlyph()
{
QFontEngine::unlockAlphaMapForGlyph();
return glyph;
}
static inline bool is2dRotation(const QTransform &t)

View File

@ -129,20 +129,6 @@ private:
class QFontEngineFT : public QFontEngine
{
public:
/* we don't cache glyphs that are too large anyway, so we can make this struct rather small */
struct Glyph {
~Glyph();
int linearAdvance : 22;
unsigned char width;
unsigned char height;
short x;
short y;
short advance;
signed char format;
uchar *data;
};
struct GlyphInfo {
int linearAdvance;
unsigned short width;
@ -241,11 +227,9 @@ private:
QFixed subPixelPosition,
const QTransform &matrix,
QFontEngine::GlyphFormat format) override;
QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition,
GlyphFormat neededFormat, const QTransform &t,
QPoint *offset) override;
Glyph *glyphData(glyph_t glyph, QFixed subPixelPosition,
GlyphFormat neededFormat, const QTransform &t) override;
bool hasInternalCaching() const override { return cacheEnabled; }
void unlockAlphaMapForGlyph() override;
bool expectsGammaCorrectedBlending() const override;
void removeGlyphFromCache(glyph_t glyph) override;

View File

@ -225,10 +225,11 @@ namespace QtAndroidMenu
QString itemText = removeAmpersandEscapes(item->text());
jstring jtext = env->NewString(reinterpret_cast<const jchar *>(itemText.data()),
itemText.length());
jint menuId = platformMenu->menuId(item);
jobject menuItem = env->CallObjectMethod(menu,
addMenuItemMethodID,
menuNoneValue,
int(item->tag()),
menuId,
order++,
jtext);
env->DeleteLocalRef(jtext);
@ -262,10 +263,11 @@ namespace QtAndroidMenu
QString itemText = removeAmpersandEscapes(item->text());
jstring jtext = env->NewString(reinterpret_cast<const jchar *>(itemText.data()),
itemText.length());
jint menuId = visibleMenuBar->menuId(item);
jobject menuItem = env->CallObjectMethod(menu,
addMenuItemMethodID,
menuNoneValue,
int(item->tag()),
menuId,
order++,
jtext);
env->DeleteLocalRef(jtext);
@ -290,7 +292,7 @@ namespace QtAndroidMenu
const QAndroidPlatformMenuBar::PlatformMenusType &menus = visibleMenuBar->menus();
if (menus.size() == 1) { // Expanded menu
QAndroidPlatformMenuItem *item = static_cast<QAndroidPlatformMenuItem *>(menus.front()->menuItemForTag(menuId));
QAndroidPlatformMenuItem *item = static_cast<QAndroidPlatformMenuItem *>(menus.front()->menuItemForId(menuId));
if (item) {
if (item->menu()) {
showContextMenu(item->menu(), QRect(), env);
@ -301,7 +303,7 @@ namespace QtAndroidMenu
}
}
} else {
QAndroidPlatformMenu *menu = static_cast<QAndroidPlatformMenu *>(visibleMenuBar->menuForTag(menuId));
QAndroidPlatformMenu *menu = static_cast<QAndroidPlatformMenu *>(visibleMenuBar->menuForId(menuId));
if (menu)
showContextMenu(menu, QRect(), env);
}
@ -341,7 +343,7 @@ namespace QtAndroidMenu
static jboolean onContextItemSelected(JNIEnv *env, jobject /*thiz*/, jint menuId, jboolean checked)
{
QMutexLocker lock(&visibleMenuMutex);
QAndroidPlatformMenuItem * item = static_cast<QAndroidPlatformMenuItem *>(visibleMenu->menuItemForTag(menuId));
QAndroidPlatformMenuItem * item = static_cast<QAndroidPlatformMenuItem *>(visibleMenu->menuItemForId(menuId));
if (item) {
if (item->menu()) {
showContextMenu(item->menu(), QRect(), env);

View File

@ -62,6 +62,7 @@ void QAndroidPlatformMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatform
m_menuItems.end(),
static_cast<QAndroidPlatformMenuItem *>(before)),
static_cast<QAndroidPlatformMenuItem *>(menuItem));
m_menuHash.insert(m_nextMenuId++, menuItem);
}
void QAndroidPlatformMenu::removeMenuItem(QPlatformMenuItem *menuItem)
@ -72,6 +73,21 @@ void QAndroidPlatformMenu::removeMenuItem(QPlatformMenuItem *menuItem)
static_cast<QAndroidPlatformMenuItem *>(menuItem));
if (it != m_menuItems.end())
m_menuItems.erase(it);
{
int maxId = -1;
QHash<int, QPlatformMenuItem *>::iterator it = m_menuHash.begin();
while (it != m_menuHash.end()) {
if (it.value() == menuItem) {
it = m_menuHash.erase(it);
} else {
maxId = qMax(maxId, it.key());
++it;
}
}
m_nextMenuId = maxId + 1;
}
}
void QAndroidPlatformMenu::syncMenuItem(QPlatformMenuItem *menuItem)
@ -139,6 +155,16 @@ void QAndroidPlatformMenu::showPopup(const QWindow *parentWindow, const QRect &t
QtAndroidMenu::showContextMenu(this, targetRect, QJNIEnvironmentPrivate());
}
QPlatformMenuItem *QAndroidPlatformMenu::menuItemForTag(quintptr tag) const
{
for (QAndroidPlatformMenuItem *menuItem : m_menuItems) {
if (menuItem->tag() == tag)
return menuItem;
}
return nullptr;
}
QPlatformMenuItem *QAndroidPlatformMenu::menuItemAt(int position) const
{
if (position < m_menuItems.size())
@ -146,13 +172,20 @@ QPlatformMenuItem *QAndroidPlatformMenu::menuItemAt(int position) const
return 0;
}
QPlatformMenuItem *QAndroidPlatformMenu::menuItemForTag(quintptr tag) const
int QAndroidPlatformMenu::menuId(QPlatformMenuItem *menu) const
{
for (QPlatformMenuItem *menuItem : m_menuItems) {
if (menuItem->tag() == tag)
return menuItem;
QHash<int, QPlatformMenuItem *>::const_iterator it;
for (it = m_menuHash.constBegin(); it != m_menuHash.constEnd(); ++it) {
if (it.value() == menu)
return it.key();
}
return 0;
return -1;
}
QPlatformMenuItem *QAndroidPlatformMenu::menuItemForId(int menuId) const
{
return m_menuHash.value(menuId);
}
QAndroidPlatformMenu::PlatformMenuItemsType QAndroidPlatformMenu::menuItems() const

View File

@ -73,6 +73,8 @@ public:
QPlatformMenuItem *menuItemAt(int position) const override;
QPlatformMenuItem *menuItemForTag(quintptr tag) const override;
QPlatformMenuItem *menuItemForId(int menuId) const;
int menuId(QPlatformMenuItem *menuItem) const;
PlatformMenuItemsType menuItems() const;
QMutex *menuItemsMutex();
@ -84,6 +86,9 @@ private:
bool m_enabled;
bool m_isVisible;
QMutex m_menuItemsMutex;
int m_nextMenuId = 0;
QHash<int, QPlatformMenuItem *> m_menuHash;
};
QT_END_NAMESPACE

View File

@ -61,6 +61,7 @@ void QAndroidPlatformMenuBar::insertMenu(QPlatformMenu *menu, QPlatformMenu *bef
m_menus.end(),
static_cast<QAndroidPlatformMenu *>(before)),
static_cast<QAndroidPlatformMenu *>(menu));
m_menuHash.insert(m_nextMenuId++, menu);
}
void QAndroidPlatformMenuBar::removeMenu(QPlatformMenu *menu)
@ -69,6 +70,30 @@ void QAndroidPlatformMenuBar::removeMenu(QPlatformMenu *menu)
m_menus.erase(std::find(m_menus.begin(),
m_menus.end(),
static_cast<QAndroidPlatformMenu *>(menu)));
int maxId = -1;
QHash<int, QPlatformMenu *>::iterator it = m_menuHash.begin();
while (it != m_menuHash.end()) {
if (it.value() == menu) {
it = m_menuHash.erase(it);
} else {
maxId = qMax(maxId, it.key());
++it;
}
}
m_nextMenuId = maxId + 1;
}
int QAndroidPlatformMenuBar::menuId(QPlatformMenu *menu) const
{
QHash<int, QPlatformMenu *>::const_iterator it;
for (it = m_menuHash.constBegin(); it != m_menuHash.constEnd(); ++it) {
if (it.value() == menu)
return it.key();
}
return -1;
}
void QAndroidPlatformMenuBar::syncMenu(QPlatformMenu *menu)
@ -86,12 +111,17 @@ void QAndroidPlatformMenuBar::handleReparent(QWindow *newParentWindow)
QPlatformMenu *QAndroidPlatformMenuBar::menuForTag(quintptr tag) const
{
for (QPlatformMenu *menu : m_menus) {
for (QAndroidPlatformMenu *menu : m_menus) {
if (menu->tag() == tag)
return menu;
}
return 0;
return nullptr;
}
QPlatformMenu *QAndroidPlatformMenuBar::menuForId(int menuId) const
{
return m_menuHash.value(menuId);
}
QWindow *QAndroidPlatformMenuBar::parentWindow() const

View File

@ -43,6 +43,7 @@
#include <qpa/qplatformmenu.h>
#include <qvector.h>
#include <qmutex.h>
#include <qhash.h>
QT_BEGIN_NAMESPACE
@ -60,6 +61,8 @@ public:
void syncMenu(QPlatformMenu *menu) override;
void handleReparent(QWindow *newParentWindow) override;
QPlatformMenu *menuForTag(quintptr tag) const override;
QPlatformMenu *menuForId(int menuId) const;
int menuId(QPlatformMenu *menu) const;
QWindow *parentWindow() const override;
PlatformMenusType menus() const;
@ -69,6 +72,9 @@ private:
PlatformMenusType m_menus;
QWindow *m_parentWindow;
QMutex m_menusListMutex;
int m_nextMenuId = 0;
QHash<int, QPlatformMenu *> m_menuHash;
};
QT_END_NAMESPACE

View File

@ -59,7 +59,6 @@
NSMenuItem *aboutItem;
NSMenuItem *aboutQtItem;
NSMenuItem *hideItem;
NSMenuItem *lastAppSpecificItem;
NSMenuItem *servicesItem;
NSMenuItem *hideAllOthersItem;
NSMenuItem *showAllItem;
@ -118,6 +117,9 @@
[appMenu addItem:[NSMenuItem separatorItem]];
// Preferences
// We'll be adding app specific items after this. The macOS HIG state that,
// "In general, a Preferences menu item should be the first app-specific menu item."
// https://developer.apple.com/macos/human-interface-guidelines/menus/menu-bar-menus/
preferencesItem = [[QCocoaNSMenuItem alloc] init];
preferencesItem.title = @"Preferences…";
preferencesItem.keyEquivalent = @",";
@ -126,11 +128,6 @@
preferencesItem.hidden = YES;
[appMenu addItem:preferencesItem];
// We'll be adding app specific items after this. The macOS HIG state that,
// "In general, a Preferences menu item should be the first app-specific menu item."
// https://developer.apple.com/macos/human-interface-guidelines/menus/menu-bar-menus/
lastAppSpecificItem = preferencesItem;
[appMenu addItem:[NSMenuItem separatorItem]];
// Services item and menu
@ -194,8 +191,6 @@
[showAllItem release];
[quitItem release];
[lastAppSpecificItem release];
[super dealloc];
}
@ -272,25 +267,20 @@
// No reason to create the item if it already exists.
for (NSMenuItem *item in appMenu.itemArray)
if (qt_objc_cast<QCocoaNSMenuItem *>(item).platformMenuItem == platformItem)
return [[item retain] autorelease];
return item;
// Create an App-Specific menu item, insert it into the menu and return
// it as an autorelease item.
QCocoaNSMenuItem *item;
if (platformItem->isSeparator())
item = [[QCocoaNSMenuItem separatorItemWithPlatformMenuItem:platformItem] retain];
item = [QCocoaNSMenuItem separatorItemWithPlatformMenuItem:platformItem];
else
item = [[QCocoaNSMenuItem alloc] initWithPlatformMenuItem:platformItem];
item = [[[QCocoaNSMenuItem alloc] initWithPlatformMenuItem:platformItem] autorelease];
const auto location = [appMenu indexOfItem:lastAppSpecificItem];
const auto location = [self indexOfLastAppSpecificMenuItem];
[appMenu insertItem:item atIndex:NSInteger(location) + 1];
if (!lastAppSpecificItem.separatorItem)
[lastAppSpecificItem release];
lastAppSpecificItem = item; // Keep track of this for later (i.e., don't release it)
[appMenu insertItem:item atIndex:location + 1];
return [[item retain] autorelease];
return item;
}
- (void)orderFrontStandardAboutPanel:(id)sender
@ -344,8 +334,24 @@
- (NSArray<NSMenuItem *> *)mergeable
{
// Don't include the quitItem here, since we want it always visible and enabled regardless
// Note that lastAppSpecificItem may be nil, so we can't use @[] here.
return [NSArray arrayWithObjects:preferencesItem, aboutItem, aboutQtItem, lastAppSpecificItem, nil];
auto items = [NSArray arrayWithObjects:preferencesItem, aboutItem, aboutQtItem,
appMenu.itemArray[[self indexOfLastAppSpecificMenuItem]], nil];
return items;
}
- (NSUInteger)indexOfLastAppSpecificMenuItem
{
// Either the 'Preferences', which is the first app specific menu item, or something
// else we appended later (thus the reverse order):
const auto location = [appMenu.itemArray indexOfObjectWithOptions:NSEnumerationReverse
passingTest:^BOOL(NSMenuItem *item, NSUInteger, BOOL *) {
if (auto qtItem = qt_objc_cast<QCocoaNSMenuItem*>(item))
return qtItem != quitItem;
return NO;
}];
Q_ASSERT(location != NSNotFound);
return location;
}
@end

View File

@ -177,6 +177,9 @@ void *QCocoaNativeInterface::NSPrintInfoForPrintEngine(QPrintEngine *printEngine
QPixmap QCocoaNativeInterface::defaultBackgroundPixmapForQWizard()
{
// Note: starting with macOS 10.14, the KeyboardSetupAssistant app bundle no
// longer contains the "Background.png" image. This function then returns a
// null pixmap.
const int ExpectedImageWidth = 242;
const int ExpectedImageHeight = 414;
QCFType<CFArrayRef> urls = LSCopyApplicationURLsForBundleIdentifier(

View File

@ -92,6 +92,7 @@ void QCocoaWindowManager::modalSessionChanged()
if (NSApp.modalWindow) {
// Lower window to that of the modal windows, but no less
nativeWindow.level = NSModalPanelWindowLevel;
if ([nativeWindow isVisible])
[nativeWindow orderBack:nil];
} else {
// Restore window's natural window level, whatever that was

View File

@ -3944,6 +3944,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
CGContextScaleCTM(ctx, -1, 1);
CGContextTranslateCTM(ctx, -frameRect.left(), 0);
} else if (tabDirection == QMacStylePrivate::West && tp == QStyleOptionTab::Beginning) {
CGContextTranslateCTM(ctx, 0, opt->rect.top());
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -frameRect.right());
} else if (tabDirection == QMacStylePrivate::East && tp == QStyleOptionTab::End) {

View File

@ -2890,7 +2890,7 @@ void QWizard::setPixmap(WizardPixmap which, const QPixmap &pixmap)
Returns the pixmap set for role \a which.
By default, the only pixmap that is set is the BackgroundPixmap on
\macos.
\macos version 10.13 and earlier.
\sa QWizardPage::pixmap(), {Elements of a Wizard Page}
*/

View File

@ -84,6 +84,8 @@ private slots:
void operator_noteq();
void resize();
void fromBits_data();
void fromBits();
};
void tst_QBitArray::size_data()
@ -610,5 +612,60 @@ void tst_QBitArray::resize()
}
void tst_QBitArray::fromBits_data()
{
QTest::addColumn<QByteArray>("data");
QTest::addColumn<int>("size");
QTest::addColumn<QBitArray>("expected");
QTest::newRow("empty") << QByteArray() << 0 << QBitArray();
auto add = [](const QByteArray &tag, const char *data) {
QTest::newRow(tag) << QByteArray(data, (tag.size() + 7) / 8) << tag.size()
<< QStringToQBitArray(tag);
};
// "0" to "0000000000000000"
for (int i = 1; i < 16; ++i) {
char zero[2] = { 0, 0 };
QByteArray pattern(i, '0');
add(pattern, zero);
}
// "1" to "1111111111111111"
for (int i = 1; i < 16; ++i) {
char one[2] = { '\xff', '\xff' };
QByteArray pattern(i, '1');
add(pattern, one);
}
// trailing 0 and 1
char zero = 1;
char one = 0;
QByteArray pzero = "1";
QByteArray pone = "0";
for (int i = 2; i < 8; ++i) {
zero <<= 1;
pzero.prepend('0');
add(pzero, &zero);
one = (one << 1) | 1;
pone.prepend('1');
add(pone, &one);
}
}
void tst_QBitArray::fromBits()
{
QFETCH(QByteArray, data);
QFETCH(int, size);
QFETCH(QBitArray, expected);
QBitArray fromBits = QBitArray::fromBits(data, size);
QCOMPARE(fromBits, expected);
QCOMPARE(QBitArray::fromBits(fromBits.bits(), fromBits.size()), expected);
}
QTEST_APPLESS_MAIN(tst_QBitArray)
#include "tst_qbitarray.moc"

View File

@ -36,6 +36,7 @@ class tst_QHighDpiScaling: public QObject
Q_OBJECT
private slots:
void factor();
void scale();
};
@ -50,6 +51,23 @@ public:
QImage::Format format() const override { return QImage::Format_ARGB32_Premultiplied; }
};
void tst_QHighDpiScaling::factor()
{
QHighDpiScaling::setGlobalFactor(2);
// Verfy that QHighDpiScaling::factor() does not crash on nullptr contexts.
QPoint fakeNativePosition = QPoint(5, 5);
QPlatformScreen *screenContext = nullptr;
QVERIFY(QHighDpiScaling::factor(screenContext) >= 0);
QVERIFY(QHighDpiScaling::factor(screenContext, &fakeNativePosition) >= 0);
QPlatformScreen *platformScreenContext = nullptr;
QVERIFY(QHighDpiScaling::factor(platformScreenContext) >= 0);
QVERIFY(QHighDpiScaling::factor(platformScreenContext, &fakeNativePosition) >= 0);
QWindow *windowContext = nullptr;
QVERIFY(QHighDpiScaling::factor(windowContext) >= 0);
QVERIFY(QHighDpiScaling::factor(windowContext, &fakeNativePosition) >= 0);
}
// QTBUG-77255: Test some scaling overloads
void tst_QHighDpiScaling::scale()
{

View File

@ -191,6 +191,7 @@ private slots:
void fontTagFace();
void clearUndoRedoStacks();
private:
void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
void buildRegExpData();
@ -3522,5 +3523,16 @@ void tst_QTextDocument::fontTagFace()
}
}
void tst_QTextDocument::clearUndoRedoStacks()
{
QTextDocument doc;
QTextCursor c(&doc);
c.insertText(QStringLiteral("lorem ipsum"));
QVERIFY(doc.isUndoAvailable());
doc.clearUndoRedoStacks(QTextDocument::UndoStack); // Don't crash
QVERIFY(!doc.isUndoAvailable());
}
QTEST_MAIN(tst_QTextDocument)
#include "tst_qtextdocument.moc"

View File

@ -417,20 +417,19 @@ void tst_QWizard::setPixmap()
QVERIFY(wizard.pixmap(QWizard::BannerPixmap).isNull());
QVERIFY(wizard.pixmap(QWizard::LogoPixmap).isNull());
QVERIFY(wizard.pixmap(QWizard::WatermarkPixmap).isNull());
#ifdef Q_OS_OSX
if (QSysInfo::macVersion() <= Q_MV_OSX(10, 13))
QVERIFY(!wizard.pixmap(QWizard::BackgroundPixmap).isNull());
#else
else
QVERIFY(wizard.pixmap(QWizard::BackgroundPixmap).isNull());
#endif
QVERIFY(page->pixmap(QWizard::BannerPixmap).isNull());
QVERIFY(page->pixmap(QWizard::LogoPixmap).isNull());
QVERIFY(page->pixmap(QWizard::WatermarkPixmap).isNull());
#ifdef Q_OS_OSX
if (QSysInfo::macVersion() <= Q_MV_OSX(10, 13))
QVERIFY(!wizard.pixmap(QWizard::BackgroundPixmap).isNull());
#else
else
QVERIFY(page->pixmap(QWizard::BackgroundPixmap).isNull());
#endif
wizard.setPixmap(QWizard::BannerPixmap, p1);
wizard.setPixmap(QWizard::LogoPixmap, p2);
wizard.setPixmap(QWizard::WatermarkPixmap, p3);

View File

@ -88,7 +88,7 @@ static void sendMousePress(QWidget *widget, const QPoint &point, Qt::MouseButton
static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons buttons = 0)
{
QTest::mouseMove(widget, point);
QMouseEvent event(QEvent::MouseMove, point, button, buttons, 0);
QMouseEvent event(QEvent::MouseMove, point, widget->mapToGlobal(point), button, buttons, 0);
QApplication::sendEvent(widget, &event);
QApplication::processEvents();
}