Merge remote-tracking branch 'origin/5.6' into 5.7

Conflicts:
	configure
	src/plugins/platforms/eglfs/qeglfsintegration.cpp
	src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp

Change-Id: Id2da7c775439adb62646d5b741ee7c638042b34b
This commit is contained in:
Liang Qi 2016-11-15 09:51:41 +01:00
commit 9808b53fde
96 changed files with 831 additions and 332 deletions

View File

@ -40,6 +40,7 @@
#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#endif

View File

@ -40,6 +40,7 @@
#ifdef BUILD_ON_MAC
#include <OpenGLES/ES2/gl.h>
#else
#define GL_GLEXT_PROTOTYPES
#include <GLES2/gl2.h>
#endif

View File

@ -40,6 +40,7 @@
#ifdef BUILD_ON_MAC
#include <OpenGLES/ES3/gl.h>
#else
#define GL_GLEXT_PROTOTYPES
#include <GLES3/gl3.h>
#endif

6
configure vendored
View File

@ -3125,14 +3125,14 @@ if [ "$Edition" = "OpenSource" ]; then
while true; do
if [ "$CFG_ANDROID_STYLE_ASSETS" = "no" ] || [ "$XPLATFORM_ANDROID" = "no" ]; then
echo "You are licensed to use this software under the terms of"
echo "the GNU Lesser General Public License (LGPL) versions 3."
echo "the GNU Lesser General Public License (LGPL) version 3."
echo "You are also licensed to use this software under the terms of"
echo "the GNU General Public License (GPL) versions 2."
echo "the GNU General Public License (GPL) version 2."
affix="either"
showGPL2="yes"
else
echo "You are licensed to use this software under the terms of"
echo "the GNU Lesser General Public License (LGPL) versions 3."
echo "the GNU Lesser General Public License (LGPL) version 3."
showGPL2="no"
affix="the"
fi

View File

@ -1,114 +0,0 @@
MAKEFILE_GENERATOR = UNIX
QMAKE_INCREMENTAL_STYLE = sublib
QMAKE_PLATFORM += android
include(linux.conf)
include(gcc-base-unix.conf)
DEFINES += QT_NO_PRINTER QT_NO_PRINTDIALOG
QT_QPA_DEFAULT_PLATFORM = minimal
NDK_ROOT = $$(ANDROID_NDK_ROOT)
isEmpty(NDK_ROOT): error("$ANDROID_NDK_ROOT is empty, please set it to something like ~/android/ndk-r7c")
NDK_HOST = $$(ANDROID_NDK_HOST)
isEmpty(NDK_HOST): error("$ANDROID_NDK_HOST is empty, please set it to something like linux-x86 or darwin-x86")
ANDROID_PLATFORM = $$(ANDROID_NDK_PLATFORM)
isEmpty(ANDROID_PLATFORM): ANDROID_PLATFORM = android-5
NDK_TOOLCHAIN_VERSION = $$(ANDROID_NDK_TOOLCHAIN_VERSION)
isEmpty(NDK_TOOLCHAIN_VERSION): NDK_TOOLCHAIN_VERSION = 4.4.3
!contains(NDK_TOOLCHAIN_VERSION, 4.4.3): ANDROID_CXXSTL_SUFFIX = -$$NDK_TOOLCHAIN_VERSION
NDK_TOOLCHAIN = $$ANDROID_NDK_TOOLCHAIN_PREFIX-$$NDK_TOOLCHAIN_VERSION
NDK_TOOLCHAIN_PATH = $$NDK_ROOT/toolchains/$$NDK_TOOLCHAIN/prebuilt/$$NDK_HOST
CONFIG += $$ANDROID_PLATFORM $$ANDROID_TARGET_ARCH
ANDROID_PLATFORM_ROOT_PATH = $$NDK_ROOT/platforms/$$ANDROID_PLATFORM/arch-$$ANDROID_ARCHITECTURE/
ANDROID_PLATFORM_PATH = $$ANDROID_PLATFORM_ROOT_PATH/usr
# used to compile platform plugins for android-4 and android-5
QMAKE_ANDROID_PLATFORM_INCDIR = $$NDK_ROOT/platforms/$$ANDROID_PLATFORM/arch-$$ANDROID_ARCHITECTURE/usr/include
QMAKE_ANDROID_PLATFORM_LIBDIR = $$NDK_ROOT/platforms/$$ANDROID_PLATFORM/arch-$$ANDROID_ARCHITECTURE/usr/lib
ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl$$ANDROID_CXXSTL_SUFFIX/gnu-libstdc++/libs/$$ANDROID_TARGET_ARCH
ANDROID_SOURCES_CXX_STL_INCDIR = $$NDK_ROOT/sources/cxx-stl$$ANDROID_CXXSTL_SUFFIX/gnu-libstdc++/include $$ANDROID_SOURCES_CXX_STL_LIBDIR/include
# modifications to g++.conf
QMAKE_CC = $$NDK_TOOLCHAIN_PATH/bin/$$ANDROID_NDK_TOOLS_PREFIX-gcc
QMAKE_CFLAGS_WARN_ON = -Wall -Wextra
QMAKE_CFLAGS_WARN_OFF = -Wno-psabi
QMAKE_CFLAGS_SHLIB = -fPIC
QMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
QMAKE_CFLAGS_THREAD = -D_REENTRANT
QMAKE_CFLAGS_HIDESYMS = -fvisibility=hidden
QMAKE_CXX = $$NDK_TOOLCHAIN_PATH/bin/$$ANDROID_NDK_TOOLS_PREFIX-g++
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
QMAKE_CXXFLAGS_RELEASE += $$QMAKE_CFLAGS_RELEASE
QMAKE_CXXFLAGS_DEBUG += $$QMAKE_CFLAGS_DEBUG
QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB
QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC
QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD
QMAKE_CXXFLAGS_HIDESYMS = $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden
QMAKE_LINK = $$QMAKE_CXX
QMAKE_LINK_SHLIB = $$QMAKE_LINK
# modifications to linux.conf
QMAKE_AR = $$NDK_TOOLCHAIN_PATH/bin/$$ANDROID_NDK_TOOLS_PREFIX-ar cqs
QMAKE_OBJCOPY = $$NDK_TOOLCHAIN_PATH/bin/$$ANDROID_NDK_TOOLS_PREFIX-objcopy
QMAKE_NM = $$NDK_TOOLCHAIN_PATH/bin/$$ANDROID_NDK_TOOLS_PREFIX-nm -P
QMAKE_STRIP = $$NDK_TOOLCHAIN_PATH/bin/$$ANDROID_NDK_TOOLS_PREFIX-strip
QMAKE_RANLIB = $$NDK_TOOLCHAIN_PATH/bin/$$ANDROID_NDK_TOOLS_PREFIX-ranlib
QMAKE_INCDIR = $$ANDROID_PLATFORM_PATH/include $$ANDROID_SOURCES_CXX_STL_INCDIR
QMAKE_LIBDIR = $$ANDROID_SOURCES_CXX_STL_LIBDIR $$ANDROID_PLATFORM_PATH/lib
QMAKE_INCDIR_X11 =
QMAKE_LIBDIR_X11 =
QMAKE_INCDIR_OPENGL =
QMAKE_INCDIR_OPENGL_ES2 =
QMAKE_LIBDIR_OPENGL_ES2 =
contains(ANDROID_TARGET_ARCH, x86): LIBGCC_PATH_FULL = $$system($$QMAKE_CC -print-libgcc-file-name)
else: LIBGCC_PATH_FULL = $$system($$QMAKE_CC -mthumb-interwork -print-libgcc-file-name)
QMAKE_LINK = $$QMAKE_CXX
QMAKE_LINK_SHLIB = $$QMAKE_CXX
QMAKE_LFLAGS = --sysroot=$$ANDROID_PLATFORM_ROOT_PATH -L$$dirname(LIBGCC_PATH_FULL) -Wl,-rpath-link=$$ANDROID_PLATFORM_PATH/lib
QMAKE_LFLAGS_APP =
QMAKE_LFLAGS_SHLIB = -Wl,--no-undefined -Wl,-z,noexecstack -shared
contains(NDK_ROOT, ".*r[56].*") {
!contains(ANDROID_PLATFORM, ".*android-[458].*") {
message("Your NDK-version is out-dated. A work-around is enabled. Consider updating your NDK (workarounds are required until r6(a))")
QMAKE_LFLAGS_SHLIB += $$ANDROID_PLATFORM_PATH/lib/crtbegin_so.o $$ANDROID_PLATFORM_PATH/lib/crtend_so.o
}
}
QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB
QMAKE_LFLAGS_SONAME =
QMAKE_LFLAGS_NOUNDEF = -Wl,--no-undefined
QMAKE_LFLAGS_RPATH = -Wl,-rpath=
# TODO: -lgnustl_static was -lstdc++, but that leads to undefined reference to
# std::__throw_bad_alloc during configure.
QMAKE_LIBS = -lsupc++ -llog -lz -lm -ldl -lc -lgcc -lgnustl_static
QMAKE_LIBS_X11 =
QMAKE_LIBS_X11SM =
QMAKE_LIBS_QT_THREAD =
QMAKE_LIBS_QT_OPENGL =
QMAKE_LIBS_QTOPIA =
QMAKE_LIBS_THREAD =
QMAKE_LIBS_OPENGL =
QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 $$QMAKE_LIBS
load(qt_config)

View File

@ -65,7 +65,7 @@
actool_output_files = $$system(\
mkdir -p $$system_quote($$QMAKE_ASSET_CATALOGS_BUILD_PATH) && \
/usr/libexec/PlistBuddy -c \'Print :com.apple.actool.compilation-results:output-files\' \
/dev/stdin <<< $($${asset_catalog_compiler.commands} 2>/dev/null) | grep \'^ .*$\', lines)
/dev/stdin <<< $($${asset_catalog_compiler.commands} 2>/dev/null) | sed -Ene \'s/^ +//p\', lines)
for (output_file, actool_output_files) {
!equals(output_file, $$asset_catalog_compiler.target): \

View File

@ -1158,6 +1158,21 @@ static inline QString toString(subSystemOption option)
return QString();
}
static inline QString toString(triState genDebugInfo, linkerDebugOption option)
{
switch (genDebugInfo) {
case unset:
break;
case _False:
return "false";
case _True:
if (option == linkerDebugOptionFastLink)
return "DebugFastLink";
return "true";
}
return QString();
}
static inline QString toString(machineTypeOption option)
{
switch (option) {
@ -1536,7 +1551,7 @@ void VCXProjectWriter::write(XmlOutput &xml, const VCLinkerTool &tool)
<< attrTagS(_EntryPointSymbol, tool.EntryPointSymbol)
<< attrTagX(_ForceSymbolReferences, tool.ForceSymbolReferences, ";")
<< attrTagS(_FunctionOrder, tool.FunctionOrder)
<< attrTagT(_GenerateDebugInformation, tool.GenerateDebugInformation)
<< attrTagS(_GenerateDebugInformation, toString(tool.GenerateDebugInformation, tool.DebugInfoOption))
<< attrTagT(_GenerateManifest, tool.GenerateManifest)
<< attrTagT(_GenerateWindowsMetadata, tool.GenerateWindowsMetadata)
<< attrTagS(_WindowsMetadataFile, tool.GenerateWindowsMetadata == _True ? tool.WindowsMetadataFile : QString())

View File

@ -1425,8 +1425,10 @@ bool VCLinkerTool::parseOption(const char* option)
}else
EnableUAC = _True;
break;
case 0x3389797: // /DEBUG
case 0x3389797: // /DEBUG[:FASTLINK]
GenerateDebugInformation = _True;
if (config->CompilerVersion >= NET2015 && strcmp(option + 7, "FASTLINK") == 0)
DebugInfoOption = linkerDebugOptionFastLink;
break;
case 0x0033896: // /DEF:filename
ModuleDefinitionFile = option+5;

View File

@ -277,6 +277,10 @@ enum inlineExpansionOption {
expandAnySuitable,
expandDefault // Not useful number, but stops the output
};
enum linkerDebugOption {
linkerDebugOptionNone,
linkerDebugOptionFastLink
};
enum linkIncrementalType {
linkIncrementalDefault,
linkIncrementalNo,
@ -590,6 +594,7 @@ public:
QStringList ForceSymbolReferences;
QString FunctionOrder;
triState GenerateDebugInformation;
linkerDebugOption DebugInfoOption;
triState GenerateMapFile;
qlonglong HeapCommitSize;
qlonglong HeapReserveSize;

View File

@ -481,8 +481,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
int end = -1;
if (func_t == E_SECTION) {
if (args.count() != 3 && args.count() != 4) {
evalError(fL1S("%1(var) section(var, sep, begin, end) requires"
" three or four arguments.").arg(func.toQString(m_tmp1)));
evalError(fL1S("section(var, sep, begin, end) requires three or four arguments."));
} else {
var = args[0];
sep = args.at(1).toQString();

View File

@ -41,38 +41,41 @@ static const struct {
const char *name;
QLibraryInfo::LibraryLocation loc;
bool raw;
bool singular;
} propList[] = {
{ "QT_SYSROOT", QLibraryInfo::SysrootPath, true },
{ "QT_INSTALL_PREFIX", QLibraryInfo::PrefixPath, false },
{ "QT_INSTALL_ARCHDATA", QLibraryInfo::ArchDataPath, false },
{ "QT_INSTALL_DATA", QLibraryInfo::DataPath, false },
{ "QT_INSTALL_DOCS", QLibraryInfo::DocumentationPath, false },
{ "QT_INSTALL_HEADERS", QLibraryInfo::HeadersPath, false },
{ "QT_INSTALL_LIBS", QLibraryInfo::LibrariesPath, false },
{ "QT_INSTALL_LIBEXECS", QLibraryInfo::LibraryExecutablesPath, false },
{ "QT_INSTALL_BINS", QLibraryInfo::BinariesPath, false },
{ "QT_INSTALL_TESTS", QLibraryInfo::TestsPath, false },
{ "QT_INSTALL_PLUGINS", QLibraryInfo::PluginsPath, false },
{ "QT_INSTALL_IMPORTS", QLibraryInfo::ImportsPath, false },
{ "QT_INSTALL_QML", QLibraryInfo::Qml2ImportsPath, false },
{ "QT_INSTALL_TRANSLATIONS", QLibraryInfo::TranslationsPath, false },
{ "QT_INSTALL_CONFIGURATION", QLibraryInfo::SettingsPath, false },
{ "QT_INSTALL_EXAMPLES", QLibraryInfo::ExamplesPath, false },
{ "QT_INSTALL_DEMOS", QLibraryInfo::ExamplesPath, false }, // Just backwards compat
{ "QT_HOST_PREFIX", QLibraryInfo::HostPrefixPath, true },
{ "QT_HOST_DATA", QLibraryInfo::HostDataPath, true },
{ "QT_HOST_BINS", QLibraryInfo::HostBinariesPath, true },
{ "QT_HOST_LIBS", QLibraryInfo::HostLibrariesPath, true },
{ "QMAKE_SPEC", QLibraryInfo::HostSpecPath, true },
{ "QMAKE_XSPEC", QLibraryInfo::TargetSpecPath, true },
{ "QT_SYSROOT", QLibraryInfo::SysrootPath, true, true },
{ "QT_INSTALL_PREFIX", QLibraryInfo::PrefixPath, false, false },
{ "QT_INSTALL_ARCHDATA", QLibraryInfo::ArchDataPath, false, false },
{ "QT_INSTALL_DATA", QLibraryInfo::DataPath, false, false },
{ "QT_INSTALL_DOCS", QLibraryInfo::DocumentationPath, false, false },
{ "QT_INSTALL_HEADERS", QLibraryInfo::HeadersPath, false, false },
{ "QT_INSTALL_LIBS", QLibraryInfo::LibrariesPath, false, false },
{ "QT_INSTALL_LIBEXECS", QLibraryInfo::LibraryExecutablesPath, false, false },
{ "QT_INSTALL_BINS", QLibraryInfo::BinariesPath, false, false },
{ "QT_INSTALL_TESTS", QLibraryInfo::TestsPath, false, false },
{ "QT_INSTALL_PLUGINS", QLibraryInfo::PluginsPath, false, false },
{ "QT_INSTALL_IMPORTS", QLibraryInfo::ImportsPath, false, false },
{ "QT_INSTALL_QML", QLibraryInfo::Qml2ImportsPath, false, false },
{ "QT_INSTALL_TRANSLATIONS", QLibraryInfo::TranslationsPath, false, false },
{ "QT_INSTALL_CONFIGURATION", QLibraryInfo::SettingsPath, false, false },
{ "QT_INSTALL_EXAMPLES", QLibraryInfo::ExamplesPath, false, false },
{ "QT_INSTALL_DEMOS", QLibraryInfo::ExamplesPath, false, false }, // Just backwards compat
{ "QT_HOST_PREFIX", QLibraryInfo::HostPrefixPath, true, false },
{ "QT_HOST_DATA", QLibraryInfo::HostDataPath, true, false },
{ "QT_HOST_BINS", QLibraryInfo::HostBinariesPath, true, false },
{ "QT_HOST_LIBS", QLibraryInfo::HostLibrariesPath, true, false },
{ "QMAKE_SPEC", QLibraryInfo::HostSpecPath, true, true },
{ "QMAKE_XSPEC", QLibraryInfo::TargetSpecPath, true, true },
};
QMakeProperty::QMakeProperty() : settings(0)
{
for (unsigned i = 0; i < sizeof(propList)/sizeof(propList[0]); i++) {
QString name = QString::fromLatin1(propList[i].name);
if (!propList[i].singular) {
m_values[ProKey(name + "/src")] = QLibraryInfo::rawLocation(propList[i].loc, QLibraryInfo::EffectiveSourcePaths);
m_values[ProKey(name + "/get")] = QLibraryInfo::rawLocation(propList[i].loc, QLibraryInfo::EffectivePaths);
}
QString val = QLibraryInfo::rawLocation(propList[i].loc, QLibraryInfo::FinalPaths);
if (!propList[i].raw) {
m_values[ProKey(name + "/dev")] = QLibraryInfo::rawLocation(propList[i].loc, QLibraryInfo::DevicePaths);

View File

@ -135,10 +135,12 @@ bool Data::valid() const
return false;
bool res = false;
if (header->root()->is_object)
res = static_cast<Object *>(header->root())->isValid();
Base *root = header->root();
int maxSize = alloc - sizeof(Header);
if (root->is_object)
res = static_cast<Object *>(root)->isValid(maxSize);
else
res = static_cast<Array *>(header->root())->isValid();
res = static_cast<Array *>(root)->isValid(maxSize);
return res;
}
@ -223,9 +225,9 @@ int Object::indexOf(QLatin1String key, bool *exists) const
return min;
}
bool Object::isValid() const
bool Object::isValid(int maxSize) const
{
if (tableOffset + length*sizeof(offset) > size)
if (size > (uint)maxSize || tableOffset + length*sizeof(offset) > size)
return false;
QString lastKey;
@ -234,8 +236,7 @@ bool Object::isValid() const
if (entryOffset + sizeof(Entry) >= tableOffset)
return false;
Entry *e = entryAt(i);
int s = e->size();
if (table()[i] + s > tableOffset)
if (!e->isValid(tableOffset - table()[i]))
return false;
QString key = e->key();
if (key < lastKey)
@ -249,9 +250,9 @@ bool Object::isValid() const
bool Array::isValid() const
bool Array::isValid(int maxSize) const
{
if (tableOffset + length*sizeof(offset) > size)
if (size > (uint)maxSize || tableOffset + length*sizeof(offset) > size)
return false;
for (uint i = 0; i < length; ++i) {
@ -359,12 +360,12 @@ bool Value::isValid(const Base *b) const
int s = usedStorage(b);
if (!s)
return true;
if (s < 0 || offset + s > (int)b->tableOffset)
if (s < 0 || s > (int)b->tableOffset - offset)
return false;
if (type == QJsonValue::Array)
return static_cast<Array *>(base(b))->isValid();
return static_cast<Array *>(base(b))->isValid(s);
if (type == QJsonValue::Object)
return static_cast<Object *>(base(b))->isValid();
return static_cast<Object *>(base(b))->isValid(s);
return true;
}

View File

@ -310,12 +310,19 @@ public:
explicit String(const char *data) { d = (Data *)data; }
struct Data {
qle_int length;
qle_uint length;
qle_ushort utf16[1];
};
Data *d;
int byteSize() const { return sizeof(uint) + sizeof(ushort) * d->length; }
bool isValid(int maxSize) const {
// Check byteSize() <= maxSize, avoiding integer overflow
maxSize -= sizeof(uint);
return maxSize >= 0 && uint(d->length) <= maxSize / sizeof(ushort);
}
inline String &operator=(const QString &str)
{
d->length = str.length();
@ -384,11 +391,16 @@ public:
explicit Latin1String(const char *data) { d = (Data *)data; }
struct Data {
qle_short length;
qle_ushort length;
char latin1[1];
};
Data *d;
int byteSize() const { return sizeof(ushort) + sizeof(char)*(d->length); }
bool isValid(int maxSize) const {
return byteSize() <= maxSize;
}
inline Latin1String &operator=(const QString &str)
{
int len = d->length = str.length();
@ -590,7 +602,7 @@ public:
int indexOf(const QString &key, bool *exists) const;
int indexOf(QLatin1String key, bool *exists) const;
bool isValid() const;
bool isValid(int maxSize) const;
};
@ -600,7 +612,7 @@ public:
inline Value at(int i) const;
inline Value &operator [](int i);
bool isValid() const;
bool isValid(int maxSize) const;
};
@ -655,12 +667,12 @@ public:
// key
// value data follows key
int size() const {
uint size() const {
int s = sizeof(Entry);
if (value.latinKey)
s += sizeof(ushort) + qFromLittleEndian(*(ushort *) ((const char *)this + sizeof(Entry)));
s += shallowLatin1Key().byteSize();
else
s += sizeof(uint) + sizeof(ushort)*qFromLittleEndian(*(int *) ((const char *)this + sizeof(Entry)));
s += shallowKey().byteSize();
return alignedSize(s);
}
@ -686,6 +698,15 @@ public:
return shallowKey().toString();
}
bool isValid(int maxSize) const {
if (maxSize < (int)sizeof(Entry))
return false;
maxSize -= sizeof(Entry);
if (value.latinKey)
return shallowLatin1Key().isValid(maxSize);
return shallowKey().isValid(maxSize);
}
bool operator ==(const QString &key) const;
inline bool operator !=(const QString &key) const { return !operator ==(key); }
inline bool operator >=(const QString &key) const;
@ -698,8 +719,6 @@ public:
bool operator >=(const Entry &other) const;
};
inline bool operator!=(const Entry &lhs, const Entry &rhs) { return !(lhs == rhs); }
inline bool Entry::operator >=(const QString &key) const
{
if (value.latinKey)

View File

@ -599,8 +599,8 @@ bool QJsonObject::operator==(const QJsonObject &other) const
for (uint i = 0; i < o->length; ++i) {
QJsonPrivate::Entry *e = o->entryAt(i);
QJsonPrivate::Entry *oe = other.o->entryAt(i);
if (*e != *oe || QJsonValue(d, o, e->value) != QJsonValue(other.d, other.o, oe->value))
QJsonValue v(d, o, e->value);
if (other.value(e->key()) != v)
return false;
}

View File

@ -42,6 +42,7 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QThread>
#include <QtCore/QHash>
#include <QtCore/QMutex>
#include <QtCore/qfunctions_winrt.h>
#include <private/qabstracteventdispatcher_p.h>
#include <private/qcoreapplication_p.h>
@ -106,6 +107,7 @@ public:
private:
QHash<int, QObject *> timerIdToObject;
QVector<WinRTTimerInfo> timerInfos;
mutable QMutex timerInfoLock;
QHash<HANDLE, int> timerHandleToId;
QHash<int, HANDLE> timerIdToHandle;
QHash<int, HANDLE> timerIdToCancelHandle;
@ -122,6 +124,7 @@ private:
timerIdToObject.insert(id, obj);
const quint64 targetTime = qt_msectime() + interval;
const WinRTTimerInfo info(id, interval, type, obj, targetTime);
QMutexLocker locker(&timerInfoLock);
if (id >= timerInfos.size())
timerInfos.resize(id + 1);
timerInfos[id] = info;
@ -130,6 +133,7 @@ private:
bool removeTimer(int id)
{
QMutexLocker locker(&timerInfoLock);
if (id >= timerInfos.size())
return false;
@ -253,6 +257,9 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
if (timerId == INTERRUPT_HANDLE)
break;
{
QMutexLocker locker(&d->timerInfoLock);
WinRTTimerInfo &info = d->timerInfos[timerId];
Q_ASSERT(info.timerId != INVALID_TIMER_ID);
@ -261,6 +268,7 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
// Update timer's targetTime
const quint64 targetTime = qt_msectime() + info.interval;
info.targetTime = targetTime;
}
waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, 0, TRUE);
}
emit awake();
@ -428,6 +436,7 @@ QList<QAbstractEventDispatcher::TimerInfo> QEventDispatcherWinRT::registeredTime
}
Q_D(const QEventDispatcherWinRT);
QMutexLocker locker(&d->timerInfoLock);
QList<TimerInfo> timerInfos;
for (const WinRTTimerInfo &info : d->timerInfos) {
if (info.object == object && info.timerId != INVALID_TIMER_ID)
@ -459,6 +468,7 @@ int QEventDispatcherWinRT::remainingTime(int timerId)
}
Q_D(QEventDispatcherWinRT);
QMutexLocker locker(&d->timerInfoLock);
const WinRTTimerInfo timerInfo = d->timerInfos.at(timerId);
if (timerInfo.timerId == INVALID_TIMER_ID) {
#ifndef QT_NO_DEBUG
@ -507,6 +517,9 @@ bool QEventDispatcherWinRT::event(QEvent *e)
case QEvent::Timer: {
QTimerEvent *timerEvent = static_cast<QTimerEvent *>(e);
const int id = timerEvent->timerId();
QMutexLocker locker(&d->timerInfoLock);
Q_ASSERT(id < d->timerInfos.size());
WinRTTimerInfo &info = d->timerInfos[id];
Q_ASSERT(info.timerId != INVALID_TIMER_ID);
@ -515,17 +528,17 @@ bool QEventDispatcherWinRT::event(QEvent *e)
break;
info.inEvent = true;
locker.unlock();
QTimerEvent te(id);
QCoreApplication::sendEvent(d->timerIdToObject.value(id), &te);
locker.relock();
// The timer might have been removed in the meanwhile
if (id >= d->timerInfos.size())
break;
info = d->timerInfos[id];
if (info.timerId == INVALID_TIMER_ID)
break;
if (info.interval == 0 && info.inEvent) {
// post the next zero timer event as long as the timer was not restarted
QCoreApplication::postEvent(this, new QTimerEvent(id));

View File

@ -886,7 +886,7 @@ inline void QXmlStreamReaderPrivate::reallocateStack()
sym_stack = reinterpret_cast<Value*> (realloc(sym_stack, stack_size * sizeof(Value)));
Q_CHECK_PTR(sym_stack);
state_stack = reinterpret_cast<int*> (realloc(state_stack, stack_size * sizeof(int)));
Q_CHECK_PTR(sym_stack);
Q_CHECK_PTR(state_stack);
}

View File

@ -380,8 +380,6 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
QThemeIconInfo info;
Q_ASSERT(!themeName.isEmpty());
QPixmap pixmap;
// Used to protect against potential recursions
visited << themeName;

View File

@ -342,8 +342,10 @@ static const char scaleFactorProperty[] = "_q_scaleFactor";
*/
void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor)
{
if (!qFuzzyCompare(factor, qreal(1))) {
m_screenFactorSet = true;
m_active = true;
}
screen->setProperty(scaleFactorProperty, QVariant(factor));
// hack to force re-evaluation of screen geometry

View File

@ -264,7 +264,7 @@ public:
static QOpenGLContextPrivate *get(QOpenGLContext *context)
{
return context->d_func();
return context ? context->d_func() : Q_NULLPTR;
}
#if !defined(QT_NO_DEBUG)

View File

@ -2502,6 +2502,9 @@ void QWindowPrivate::_q_clearAlert()
See the \l{Qt::CursorShape}{list of predefined cursor objects} for a
range of useful shapes.
If no cursor has been set, or after a call to unsetCursor(), the
parent window's cursor is used.
By default, the cursor has the Qt::ArrowCursor shape.
Some underlying window implementations will reset the cursor if it

View File

@ -95,6 +95,13 @@ typedef void* GLeglImageOES;
// applications cannot target ES 3. Therefore QOpenGLFunctions and
// friends do everything dynamically and never rely on these macros.
// Some Khronos headers use the ext proto guard in the standard headers as well,
// which is bad. Work it around, but avoid spilling over to the ext header.
# ifndef GL_GLEXT_PROTOTYPES
# define GL_GLEXT_PROTOTYPES
# define QGL_TEMP_GLEXT_PROTO
# endif
# if defined(QT_OPENGL_ES_3_1)
# include <GLES3/gl31.h>
# elif defined(QT_OPENGL_ES_3)
@ -106,6 +113,11 @@ typedef void* GLeglImageOES;
# include <GLES2/gl2.h>
#endif
# ifdef QGL_TEMP_GLEXT_PROTO
# undef GL_GLEXT_PROTOTYPES
# undef QGL_TEMP_GLEXT_PROTO
# endif
/*
Some GLES2 implementations (like the one on Harmattan) are missing the
typedef for GLchar. Work around it here by adding it. The Kkronos headers
@ -126,7 +138,15 @@ typedef char GLchar;
# include <OpenGL/glext.h>
# else
# define GL_GLEXT_LEGACY // Prevents GL/gl.h from #including system glext.h
// Some Khronos headers use the ext proto guard in the standard headers as well,
// which is bad. Work it around, but avoid spilling over to the ext header.
# ifndef GL_GLEXT_PROTOTYPES
# define GL_GLEXT_PROTOTYPES
# include <GL/gl.h>
# undef GL_GLEXT_PROTOTYPES
# else
# include <GL/gl.h>
# endif
# include <QtGui/qopenglext.h>
# endif // Q_OS_MAC
#endif // QT_OPENGL_ES_2

View File

@ -955,6 +955,12 @@ QOpenGLFramebufferObject::~QOpenGLFramebufferObject()
d->stencil_buffer_guard->free();
if (d->fbo_guard)
d->fbo_guard->free();
QOpenGLContextPrivate *contextPrv = QOpenGLContextPrivate::get(QOpenGLContext::currentContext());
if (contextPrv && contextPrv->qgl_current_fbo == this) {
contextPrv->qgl_current_fbo_invalid = true;
contextPrv->qgl_current_fbo = Q_NULLPTR;
}
}
/*!

View File

@ -1766,6 +1766,10 @@ QTextBlock QTextDocument::lastBlock() const
\property QTextDocument::pageSize
\brief the page size that should be used for laying out the document
The units are determined by the underlying paint device. The size is
measured in logical pixels when painting to the screen, and in points
(1/72 inch) when painting to a printer.
By default, for a newly-created, empty document, this property contains
an undefined size.

View File

@ -1902,11 +1902,15 @@ void QTextLine::layout_helper(int maxGlyphs)
++lbh.glyphCount;
if (lbh.checkFullOtherwiseExtend(line))
goto found;
} else if (attributes[lbh.currentPosition].whiteSpace) {
} else if (attributes[lbh.currentPosition].whiteSpace
&& eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak) {
lbh.whiteSpaceOrObject = true;
while (lbh.currentPosition < end && attributes[lbh.currentPosition].whiteSpace)
while (lbh.currentPosition < end
&& attributes[lbh.currentPosition].whiteSpace
&& eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak) {
addNextCluster(lbh.currentPosition, end, lbh.spaceData, lbh.glyphCount,
current, lbh.logClusters, lbh.glyphs);
}
if (!lbh.manualWrap && lbh.spaceData.textWidth > line.width) {
lbh.spaceData.textWidth = line.width; // ignore spaces that fall out of the line.

View File

@ -587,6 +587,7 @@ qint64 QNativeSocketEngine::bytesAvailable() const
if (d->socketType != QAbstractSocket::TcpSocket)
return -1;
QMutexLocker locker(&d->readMutex);
return d->readBytes.size() - d->readBytes.pos();
}
@ -599,12 +600,12 @@ qint64 QNativeSocketEngine::read(char *data, qint64 maxlen)
// There will be a read notification when the socket was closed by the remote host. If that
// happens and there isn't anything left in the buffer, we have to return -1 in order to signal
// the closing of the socket.
QMutexLocker mutexLocker(&d->readMutex);
if (d->readBytes.pos() == d->readBytes.size() && d->socketState != QAbstractSocket::ConnectedState) {
close();
return -1;
}
QMutexLocker mutexLocker(&d->readMutex);
return d->readBytes.read(data, maxlen);
}
@ -635,6 +636,7 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHea
PacketHeaderOptions)
{
Q_D(QNativeSocketEngine);
QMutexLocker locker(&d->readMutex);
if (d->socketType != QAbstractSocket::UdpSocket || d->pendingDatagrams.isEmpty()) {
if (header)
header->clear();
@ -654,6 +656,7 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHea
} else {
readOrigin = datagram.data;
}
locker.unlock();
memcpy(data, readOrigin, qMin(maxlen, qint64(datagram.data.length())));
return readOrigin.length();
}
@ -691,12 +694,14 @@ qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QI
bool QNativeSocketEngine::hasPendingDatagrams() const
{
Q_D(const QNativeSocketEngine);
QMutexLocker locker(&d->readMutex);
return d->pendingDatagrams.length() > 0;
}
qint64 QNativeSocketEngine::pendingDatagramSize() const
{
Q_D(const QNativeSocketEngine);
QMutexLocker locker(&d->readMutex);
if (d->pendingDatagrams.isEmpty())
return -1;
@ -1346,7 +1351,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
hr = byteArrayAccess->Buffer(&data);
Q_ASSERT_SUCCEEDED(hr);
readMutex.lock();
QMutexLocker locker(&readMutex);
if (readBytes.atEnd()) // Everything has been read; the buffer is safe to reset
readBytes.close();
if (!readBytes.isOpen())
@ -1356,7 +1361,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
Q_ASSERT(readBytes.atEnd());
readBytes.write(reinterpret_cast<const char*>(data), qint64(bufferLength));
readBytes.seek(readPos);
readMutex.unlock();
locker.unlock();
if (notifyOnRead)
emit q->readReady();
@ -1420,7 +1425,9 @@ HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, I
datagram.data.resize(length);
hr = reader->ReadBytes(length, reinterpret_cast<BYTE *>(datagram.data.data()));
RETURN_OK_IF_FAILED("Could not read datagram");
QMutexLocker locker(&readMutex);
pendingDatagrams.append(datagram);
locker.unlock();
if (notifyOnRead)
emit q->readReady();

View File

@ -206,10 +206,18 @@ private:
Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocketListener> tcpListener;
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> connectOp;
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32>> readOp;
QBuffer readBytes;
QMutex readMutex;
// Protected by readMutex. Written in handleReadyRead (native callback)
QBuffer readBytes;
// In case of TCP readMutex protects readBytes and bytesAvailable. In case of UDP it is
// pendingDatagrams. They are written inside native callbacks (handleReadyRead and
// handleNewDatagrams/putIntoPendingDatagramsList)
mutable QMutex readMutex;
// Protected by readMutex. Written in handleNewDatagrams/putIntoPendingDatagramsList
QList<WinRtDatagram> pendingDatagrams;
QList<ABI::Windows::Networking::Sockets::IStreamSocket *> pendingConnections;
QList<ABI::Windows::Networking::Sockets::IStreamSocket *> currentConnections;
QEventLoop eventLoop;

View File

@ -85,6 +85,35 @@
relayed to the function retrieved by QGuiApplication.
*/
/*!
\typedef QXcbWindowFunctions::SetWmWindowRole
\since 5.6.2
This is the typedef for the function returned by
QGuiApplication::platformFunction when passed the
value returned by setWmWindowRoleIdentifier().
*/
/*!
\fn QByteArray QXcbWindowFunctions::setWmWindowRoleIdentifier()
\since 5.6.2
This function returns the byte array that can be used to query
QGuiApplication::platformFunction to retrieve the SetWmWindowRole function.
*/
/*!
\fn void QXcbWindowFunctions::setWmWindowRole(QWindow *window, const QByteArray &role)
\since 5.6.2
Sets the WM_WINDOW_ROLE property from \role on the corresponding
X11 window.
This is a convenience function that can be used directly instead
of resolving the function pointer. \a window and \a role will be
relayed to the function retrieved by QGuiApplication.
*/
/*!
\typedef QXcbWindowFunctions::SetWmWindowIconText

View File

@ -117,7 +117,7 @@ static inline int stretchFromFcWidth(int fcwidth)
return qtstretch;
}
static const char *specialLanguages[] = {
static const char specialLanguages[][6] = {
"", // Unknown
"", // Inherited
"", // Common
@ -251,12 +251,12 @@ static const char *specialLanguages[] = {
"", // OldHungarian
"" // SignWriting
};
Q_STATIC_ASSERT(sizeof(specialLanguages) / sizeof(const char *) == QChar::ScriptCount);
Q_STATIC_ASSERT(sizeof specialLanguages / sizeof *specialLanguages == QChar::ScriptCount);
// this could become a list of all languages used for each writing
// system, instead of using the single most common language.
static const char *languageForWritingSystem[] = {
0, // Any
static const char languageForWritingSystem[][6] = {
"", // Any
"en", // Latin
"el", // Greek
"ru", // Cyrillic
@ -286,25 +286,25 @@ static const char *languageForWritingSystem[] = {
"ja", // Japanese
"ko", // Korean
"vi", // Vietnamese
0, // Symbol
"", // Symbol
"sga", // Ogham
"non", // Runic
"man" // N'Ko
};
Q_STATIC_ASSERT(sizeof(languageForWritingSystem) / sizeof(const char *) == QFontDatabase::WritingSystemsCount);
Q_STATIC_ASSERT(sizeof languageForWritingSystem / sizeof *languageForWritingSystem == QFontDatabase::WritingSystemsCount);
#if FC_VERSION >= 20297
// Newer FontConfig let's us sort out fonts that report certain scripts support,
// but no open type tables for handling them correctly.
// Check the reported script presence in the FC_CAPABILITY's "otlayout:" section.
static const char *capabilityForWritingSystem[] = {
0, // Any
0, // Latin
0, // Greek
0, // Cyrillic
0, // Armenian
0, // Hebrew
0, // Arabic
static const char capabilityForWritingSystem[][5] = {
"", // Any
"", // Latin
"", // Greek
"", // Cyrillic
"", // Armenian
"", // Hebrew
"", // Arabic
"syrc", // Syriac
"thaa", // Thaana
"deva", // Devanagari
@ -317,20 +317,20 @@ static const char *capabilityForWritingSystem[] = {
"knda", // Kannada
"mlym", // Malayalam
"sinh", // Sinhala
0, // Thai
0, // Lao
"", // Thai
"", // Lao
"tibt", // Tibetan
"mymr", // Myanmar
0, // Georgian
"", // Georgian
"khmr", // Khmer
0, // SimplifiedChinese
0, // TraditionalChinese
0, // Japanese
0, // Korean
0, // Vietnamese
0, // Symbol
0, // Ogham
0, // Runic
"", // SimplifiedChinese
"", // TraditionalChinese
"", // Japanese
"", // Korean
"", // Vietnamese
"", // Symbol
"", // Ogham
"", // Runic
"nko " // N'Ko
};
Q_STATIC_ASSERT(sizeof(capabilityForWritingSystem) / sizeof(*capabilityForWritingSystem) == QFontDatabase::WritingSystemsCount);
@ -436,7 +436,7 @@ static void populateFromPattern(FcPattern *pattern)
FcLangResult langRes = FcLangSetHasLang(langset, lang);
if (langRes != FcLangDifferentLang) {
#if FC_VERSION >= 20297
if (capabilityForWritingSystem[j] != Q_NULLPTR && requiresOpenType(j)) {
if (*capabilityForWritingSystem[j] && requiresOpenType(j)) {
if (cap == Q_NULLPTR)
capRes = FcPatternGetString(pattern, FC_CAPABILITY, 0, &cap);
if (capRes == FcResultMatch && strstr(reinterpret_cast<const char *>(cap), capabilityForWritingSystem[j]) == 0)

View File

@ -45,6 +45,7 @@
#include "qcocoacolordialoghelper.h"
#include "qcocoahelpers.h"
#include "qcocoaeventdispatcher.h"
#import <AppKit/AppKit.h>
@ -322,6 +323,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
// cleanup of modal sessions. Do this before showing the native dialog, otherwise it will
// close down during the cleanup.
qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
// Make sure we don't interrupt the runModalForWindow call.
QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag();
[NSApp runModalForWindow:mColorPanel];
mDialogIsExecuting = false;
return (mResultCode == NSOKButton);

View File

@ -85,7 +85,10 @@ void QCocoaCursor::setPos(const QPoint &position)
NSCursor *QCocoaCursor::convertCursor(QCursor *cursor)
{
const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor;
if (cursor == Q_NULLPTR)
return 0;
const Qt::CursorShape newShape = cursor->shape();
NSCursor *cocoaCursor;
// Check for a suitable built-in NSCursor first:

View File

@ -131,6 +131,8 @@ public:
void interrupt();
void flush();
static void clearCurrentThreadCocoaEventDispatcherInterruptFlag();
friend void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher);
};

View File

@ -966,6 +966,19 @@ void QCocoaEventDispatcher::interrupt()
void QCocoaEventDispatcher::flush()
{ }
// QTBUG-56746: The behavior of processEvents() has been changed to not clear
// the interrupt flag. Use this function to clear it.
void QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag()
{
QCocoaEventDispatcher *cocoaEventDispatcher =
qobject_cast<QCocoaEventDispatcher *>(QThread::currentThread()->eventDispatcher());
if (!cocoaEventDispatcher)
return;
QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate =
static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
cocoaEventDispatcherPrivate->interrupt = false;
}
QCocoaEventDispatcher::~QCocoaEventDispatcher()
{
Q_D(QCocoaEventDispatcher);

View File

@ -53,6 +53,7 @@
#include "qt_mac_p.h"
#include "qcocoahelpers.h"
#include "qcocoamenubar.h"
#include "qcocoaeventdispatcher.h"
#include <qregexp.h>
#include <qbuffer.h>
#include <qdebug.h>
@ -243,6 +244,10 @@ static QString strippedText(QString s)
// cleanup of modal sessions. Do this before showing the native dialog, otherwise it will
// close down during the cleanup.
qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
// Make sure we don't interrupt the runModal call below.
QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag();
QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder();
mReturnCode = [mSavePanel runModal];
QCocoaMenuBar::resetKnownMenuItemsToQt();

View File

@ -49,6 +49,7 @@
#include "qcocoafontdialoghelper.h"
#include "qcocoahelpers.h"
#include "qcocoaeventdispatcher.h"
#import <AppKit/AppKit.h>
@ -319,6 +320,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
// cleanup of modal sessions. Do this before showing the native dialog, otherwise it will
// close down during the cleanup.
qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
// Make sure we don't interrupt the runModalForWindow call.
QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag();
[NSApp runModalForWindow:mFontPanel];
mDialogIsExecuting = false;
return (mResultCode == NSOKButton);

View File

@ -100,6 +100,8 @@ private:
*/
Q_INVOKABLE QPixmap defaultBackgroundPixmapForQWizard();
Q_INVOKABLE void clearCurrentThreadCocoaEventDispatcherInterruptFlag();
// QMacPastebardMime support. The mac pasteboard void pointers are
// QMacPastebardMime instances from the cocoa plugin or qtmacextras
// These two classes are kept in sync and can be casted between.

View File

@ -44,6 +44,7 @@
#include "qcocoahelpers.h"
#include "qcocoaapplication.h"
#include "qcocoaintegration.h"
#include "qcocoaeventdispatcher.h"
#include <qbytearray.h>
#include <qwindow.h>
@ -194,6 +195,11 @@ QPixmap QCocoaNativeInterface::defaultBackgroundPixmapForQWizard()
return QPixmap();
}
void QCocoaNativeInterface::clearCurrentThreadCocoaEventDispatcherInterruptFlag()
{
QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag();
}
void QCocoaNativeInterface::onAppFocusWindowChanged(QWindow *window)
{
Q_UNUSED(window);

View File

@ -242,6 +242,8 @@ public:
void setMenubar(QCocoaMenuBar *mb);
QCocoaMenuBar *menubar() const;
NSCursor *effectiveWindowCursor() const;
void applyEffectiveWindowCursor();
void setWindowCursor(NSCursor *cursor);
void registerTouch(bool enable);

View File

@ -1663,31 +1663,53 @@ QCocoaMenuBar *QCocoaWindow::menubar() const
return m_menubar;
}
void QCocoaWindow::setWindowCursor(NSCursor *cursor)
// Finds the effective cursor for this window by walking up the
// ancestor chain (including this window) until a set cursor is
// found. Returns nil if there is not set cursor.
NSCursor *QCocoaWindow::effectiveWindowCursor() const
{
// This function is called (via QCocoaCursor) by Qt to set
// the cursor for this window. It can be called for a window
// that is not currenly under the mouse pointer (for example
// for a popup window.) Qt expects the set cursor to "stick":
// it should be accociated with the window until a different
// cursor is set.
if (m_windowCursor != cursor) {
[m_windowCursor release];
m_windowCursor = [cursor retain];
if (m_windowCursor)
return m_windowCursor;
if (!parent())
return nil;
return static_cast<QCocoaWindow *>(parent())->effectiveWindowCursor();
}
// Use the built in cursor rect API if the QCocoaWindow has a NSWindow.
// Othervise, set the cursor if this window is under the mouse. In
// this case QNSView::cursorUpdate will set the cursor as the pointer
// moves.
if (m_nsWindow && m_qtView) {
[m_nsWindow invalidateCursorRectsForView : m_qtView];
// Applies the cursor as returned by effectiveWindowCursor(), handles
// the special no-cursor-set case by setting the arrow cursor.
void QCocoaWindow::applyEffectiveWindowCursor()
{
NSCursor *effectiveCursor = effectiveWindowCursor();
if (effectiveCursor) {
[effectiveCursor set];
} else {
if (m_windowUnderMouse)
[cursor set];
// We wold like to _unset_ the cursor here; but there is no such
// API. Fall back to setting the default arrow cursor.
[[NSCursor arrowCursor] set];
}
}
void QCocoaWindow::setWindowCursor(NSCursor *cursor)
{
if (m_windowCursor == cursor)
return;
// Setting a cursor in a foregin view is not supported.
if (!m_qtView)
return;
[m_windowCursor release];
m_windowCursor = cursor;
[m_windowCursor retain];
// The installed view tracking area (see QNSView updateTrackingAreas) will
// handle cursor updates on mouse enter/leave. Handle the case where the
// mouse is on the this window by changing the cursor immediately.
if (m_windowUnderMouse)
applyEffectiveWindowCursor();
}
void QCocoaWindow::registerTouch(bool enable)
{
m_registerTouchCount += enable ? 1 : -1;

View File

@ -131,7 +131,6 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
- (void)mouseMovedImpl:(NSEvent *)theEvent;
- (void)mouseEnteredImpl:(NSEvent *)theEvent;
- (void)mouseExitedImpl:(NSEvent *)theEvent;
- (void)cursorUpdateImpl:(NSEvent *)theEvent;
- (void)rightMouseDown:(NSEvent *)theEvent;
- (void)rightMouseDragged:(NSEvent *)theEvent;
- (void)rightMouseUp:(NSEvent *)theEvent;

View File

@ -125,7 +125,7 @@ static bool _q_dontOverrideCtrlLMB = false;
- (void)cursorUpdate:(NSEvent *)theEvent
{
[view cursorUpdateImpl:theEvent];
[self cursorUpdate:theEvent];
}
@end
@ -1071,21 +1071,10 @@ QT_WARNING_POP
[self addTrackingArea:m_trackingArea];
}
-(void)cursorUpdateImpl:(NSEvent *)theEvent
- (void)cursorUpdate:(NSEvent *)theEvent
{
Q_UNUSED(theEvent)
// Set the cursor manually if there is no NSWindow.
if (!m_platformWindow->m_nsWindow && m_platformWindow->m_windowCursor)
[m_platformWindow->m_windowCursor set];
else
[super cursorUpdate:theEvent];
}
-(void)resetCursorRects
{
// Use the cursor rect API if there is a NSWindow
if (m_platformWindow->m_nsWindow && m_platformWindow->m_windowCursor)
[self addCursorRect:[self visibleRect] cursor:m_platformWindow->m_windowCursor];
Q_UNUSED(theEvent);
m_platformWindow->applyEffectiveWindowCursor();
}
- (void)mouseMovedImpl:(NSEvent *)theEvent
@ -1915,9 +1904,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
- (NSRange) selectedRange
{
NSRange selectedRange = {NSNotFound, 0};
selectedRange.location = NSNotFound;
selectedRange.length = 0;
NSRange selectedRange = {0, 0};
QObject *fo = QGuiApplication::focusObject();
if (!fo)

View File

@ -418,15 +418,17 @@ void QEglFSIntegration::createInputHandlers()
}
#endif
bool useTslib = false;
#ifndef QT_NO_TSLIB
useTslib = qEnvironmentVariableIntValue("QT_QPA_EGLFS_TSLIB");
if (useTslib)
new QTsLibMouseHandler(QLatin1String("TsLib"), QString() /* spec */);
#endif
#if !defined(QT_NO_EVDEV) && !defined(Q_OS_ANDROID)
m_kbdMgr = new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this);
new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this);
#ifndef QT_NO_TSLIB
const bool useTslib = qEnvironmentVariableIntValue("QT_QPA_EGLFS_TSLIB");
if (useTslib)
new QTsLibMouseHandler(QLatin1String("TsLib"), QString() /* spec */);
else
#endif // QT_NO_TSLIB
if (!useTslib)
new QEvdevTouchManager(QLatin1String("EvdevTouch"), QString() /* spec */, this);
#endif
}

View File

@ -625,7 +625,7 @@
- (id<UITextInputTokenizer>)tokenizer
{
return [[[UITextInputStringTokenizer alloc] initWithTextInput:id<UITextInput>(self)] autorelease];
return [[[UITextInputStringTokenizer alloc] initWithTextInput:self] autorelease];
}
- (UITextPosition *)beginningOfDocument

View File

@ -147,15 +147,17 @@ void QLinuxFbIntegration::createInputHandlers()
}
#endif
bool useTslib = false;
#ifndef QT_NO_TSLIB
useTslib = qEnvironmentVariableIntValue("QT_QPA_FB_TSLIB");
if (useTslib)
new QTsLibMouseHandler(QLatin1String("TsLib"), QString());
#endif
#if !defined(QT_NO_EVDEV) && !defined(Q_OS_ANDROID)
new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this);
new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this);
#ifndef QT_NO_TSLIB
const bool useTslib = qEnvironmentVariableIntValue("QT_QPA_FB_TSLIB");
if (useTslib)
new QTsLibMouseHandler(QLatin1String("TsLib"), QString());
else
#endif // QT_NO_TSLIB
if (!useTslib)
new QEvdevTouchManager(QLatin1String("EvdevTouch"), QString() /* spec */, this);
#endif
}

View File

@ -678,8 +678,11 @@ void QGLXContext::queryDummyContext()
}
QOpenGLContext context;
context.create();
context.makeCurrent(surface.data());
if (!context.create() || !context.makeCurrent(surface.data())) {
qWarning("QGLXContext: Failed to create dummy context");
m_supportsThreading = false;
return;
}
m_supportsThreading = true;

View File

@ -729,8 +729,10 @@ void QXcbClipboard::handleXFixesSelectionRequest(xcb_xfixes_selection_notify_eve
if (mode > QClipboard::Selection)
return;
// here we care only about the xfixes events that come from non Qt processes
if (event->owner != XCB_NONE && event->owner != owner()) {
// Note1: Here we care only about the xfixes events that come from other processes.
// Note2: If the QClipboard::clear() is issued, event->owner is XCB_NONE,
// so we check selection_timestamp to not handle our own QClipboard::clear().
if (event->owner != owner() && event->selection_timestamp > m_timestamp[mode]) {
if (!m_xClipboard[mode]) {
m_xClipboard[mode].reset(new QXcbClipboardMime(mode, this));
} else {

View File

@ -133,6 +133,11 @@ void QMacPageSetupDialogPrivate::openCocoaPageLayout(Qt::WindowModality modality
QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) alloc] initWithNSPrintInfo:printInfo];
if (modality == Qt::ApplicationModal) {
// Make sure we don't interrupt the runModalWithPrintInfo call.
(void) QMetaObject::invokeMethod(qApp->platformNativeInterface(),
"clearCurrentThreadCocoaEventDispatcherInterruptFlag");
int rval = [pageLayout runModalWithPrintInfo:printInfo];
[delegate pageLayoutDidEnd:pageLayout returnCode:rval contextInfo:q];
} else {

View File

@ -245,6 +245,11 @@ void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality)
if (modality == Qt::ApplicationModal || !q->parentWidget()) {
if (modality == Qt::NonModal)
qWarning("QPrintDialog is required to be modal on OS X");
// Make sure we don't interrupt the runModalWithPrintInfo call.
(void) QMetaObject::invokeMethod(qApp->platformNativeInterface(),
"clearCurrentThreadCocoaEventDispatcherInterruptFlag");
int rval = [printPanel runModalWithPrintInfo:printInfo];
[delegate printPanelDidEnd:printPanel returnCode:rval contextInfo:q];
} else {

View File

@ -137,11 +137,3 @@ setUpdatesEnabled(false);
bigVisualChanges();
setUpdatesEnabled(true);
//! [13]
//! [14]
...
extern void qt_x11_set_global_double_buffer(bool);
qt_x11_set_global_double_buffer(false);
...
//! [14]

View File

@ -694,8 +694,7 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics
bool QGraphicsSceneBspTreeIndex::event(QEvent *event)
{
Q_D(QGraphicsSceneBspTreeIndex);
switch (event->type()) {
case QEvent::Timer:
if (event->type() == QEvent::Timer) {
if (d->indexTimerId && static_cast<QTimerEvent *>(event)->timerId() == d->indexTimerId) {
if (d->restartIndexTimer) {
d->restartIndexTimer = false;
@ -704,11 +703,8 @@ bool QGraphicsSceneBspTreeIndex::event(QEvent *event)
d->_q_updateIndex();
}
}
// Fallthrough intended - support timers in subclasses.
default:
return QObject::event(event);
}
return true;
return QObject::event(event);
}
QT_END_NAMESPACE

View File

@ -1456,6 +1456,7 @@ bool QGraphicsWidget::event(QEvent *event)
case QEvent::GraphicsSceneMousePress:
if (d->hasDecoration() && windowFrameEvent(event))
return true;
break;
case QEvent::GraphicsSceneMouseMove:
case QEvent::GraphicsSceneMouseRelease:
case QEvent::GraphicsSceneMouseDoubleClick:

View File

@ -9631,11 +9631,6 @@ void QWidget::leaveEvent(QEvent *)
Since Qt 4.0, QWidget automatically double-buffers its painting, so there
is no need to write double-buffering code in paintEvent() to avoid flicker.
\b{Note for the X11 platform}: It is possible to toggle global double
buffering by calling \c qt_x11_set_global_double_buffer(). For example,
\snippet code/src_gui_kernel_qwidget.cpp 14
\note Generally, you should refrain from calling update() or repaint()
\b{inside} a paintEvent(). For example, calling update() or repaint() on
children inside a paintevent() results in undefined behavior; the child may

View File

@ -49,6 +49,8 @@
#include "qstylehelper_p.h"
#include <qstringbuilder.h>
#include <qdatastream.h>
#include <qcryptographichash.h>
QT_BEGIN_NAMESPACE
@ -62,7 +64,6 @@ QString uniqueName(const QString &key, const QStyleOption *option, const QSize &
QString tmp = key % HexString<uint>(option->state)
% HexString<uint>(option->direction)
% HexString<uint>(complexOption ? uint(complexOption->activeSubControls) : 0u)
% HexString<quint64>(option->palette.cacheKey())
% HexString<uint>(size.width())
% HexString<uint>(size.height());
@ -73,6 +74,25 @@ QString uniqueName(const QString &key, const QStyleOption *option, const QSize &
% QLatin1Char(spinBox->frame ? '1' : '0'); ;
}
#endif // QT_NO_SPINBOX
// QTBUG-56743, try to create a palette cache key reflecting the value,
// as leaks may occur in conjunction with QStyleSheetStyle/QRenderRule modifying
// palettes when using QPalette::cacheKey()
if (option->palette != QGuiApplication::palette()) {
tmp.append(QLatin1Char('P'));
#ifndef QT_NO_DATASTREAM
QByteArray key;
key.reserve(5120); // Observed 5040B for a serialized palette on 64bit
{
QDataStream str(&key, QIODevice::WriteOnly);
str << option->palette;
}
const QByteArray sha1 = QCryptographicHash::hash(key, QCryptographicHash::Sha1).toHex();
tmp.append(QString::fromLatin1(sha1));
#else // QT_NO_DATASTREAM
tmp.append(QString::number(option->palette.cacheKey(), 16));
#endif // !QT_NO_DATASTREAM
}
return tmp;
}

View File

@ -585,6 +585,7 @@ QSize QLabelPrivate::sizeForWidth(int w) const
#ifndef QT_NO_MOVIE
} else if (movie && !movie->currentPixmap().isNull()) {
br = movie->currentPixmap().rect();
br.setSize(br.size() / movie->currentPixmap().devicePixelRatio());
#endif
} else if (isTextLabel) {
int align = QStyle::visualAlignment(textDirection(), QFlag(this->align));

View File

@ -58,11 +58,3 @@ my @zlib_headers = ( "zconf.h", "zlib.h" );
@ignore_for_include_check = ( "qsystemdetection.h", "qcompilerdetection.h", "qprocessordetection.h", @zlib_headers, @angle_headers);
@ignore_for_qt_begin_namespace_check = ( "qconfig.h", "qconfig-dist.h", "qconfig-large.h", "qconfig-medium.h", "qconfig-minimal.h", "qconfig-small.h", "qfeatures.h", "qatomic_arch.h", "qatomic_windowsce.h", "qt_windows.h", "qatomic_macosx.h", @zlib_headers, @angle_headers);
%inject_headers = ( "$basedir/src/corelib/global" => [ "qconfig.h", "qfeatures.h" ] );
# Module dependencies.
# Every module that is required to build this module should have one entry.
# Each of the module version specifiers can take one of the following values:
# - A specific Git revision.
# - any git symbolic ref resolvable from the module's repository (e.g. "refs/heads/master" to track master branch)
#
%dependencies = (
);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -93,6 +93,7 @@ private Q_SLOTS:
void fromBinary();
void toAndFromBinary_data();
void toAndFromBinary();
void invalidBinaryData();
void parseNumbers();
void parseStrings();
void parseDuplicateKeys();
@ -1764,6 +1765,21 @@ void tst_QtJson::toAndFromBinary()
QCOMPARE(doc, outdoc);
}
void tst_QtJson::invalidBinaryData()
{
QDir dir(testDataDir + "/invalidBinaryData");
QFileInfoList files = dir.entryInfoList();
for (int i = 0; i < files.size(); ++i) {
if (!files.at(i).isFile())
continue;
QFile file(files.at(i).filePath());
file.open(QIODevice::ReadOnly);
QByteArray bytes = file.readAll();
QJsonDocument document = QJsonDocument::fromRawData(bytes.constData(), bytes.size());
QVERIFY(document.isNull());
}
}
void tst_QtJson::parseNumbers()
{
{

View File

@ -162,6 +162,7 @@ private:
const QString m_prefix;
const QString m_convertFromImage;
const QString m_loadFromData;
const QTemporaryDir m_tempDir;
};
static bool lenientCompare(const QPixmap &actual, const QPixmap &expected)
@ -209,11 +210,11 @@ void tst_QPixmap::initTestCase()
QVERIFY(!m_prefix.isEmpty());
QVERIFY(!m_convertFromImage.isEmpty());
QVERIFY(!m_loadFromData.isEmpty());
QVERIFY2(m_tempDir.isValid(), qPrintable(m_tempDir.errorString()));
}
void tst_QPixmap::cleanupTestCase()
{
QFile::remove(QLatin1String("temp_image.png"));
}
void tst_QPixmap::swap()
@ -1455,18 +1456,18 @@ void tst_QPixmap::preserveDepth()
void tst_QPixmap::loadAsBitmapOrPixmap()
{
QImage tmp(10, 10, QImage::Format_RGB32);
tmp.save("temp_image.png");
tmp.save(m_tempDir.path() + "/temp_image.png");
bool ok;
// Check that we can load the pixmap as a pixmap and that it then turns into a pixmap
QPixmap pixmap("temp_image.png");
QPixmap pixmap(m_tempDir.path() + "/temp_image.png");
QVERIFY(!pixmap.isNull());
QVERIFY(pixmap.depth() > 1);
QVERIFY(!pixmap.isQBitmap());
pixmap = QPixmap();
ok = pixmap.load("temp_image.png");
ok = pixmap.load(m_tempDir.path() + "/temp_image.png");
QVERIFY(ok);
QVERIFY(!pixmap.isNull());
QVERIFY(pixmap.depth() > 1);
@ -1474,20 +1475,20 @@ void tst_QPixmap::loadAsBitmapOrPixmap()
//now we can try to load it without an extension
pixmap = QPixmap();
ok = pixmap.load("temp_image");
ok = pixmap.load(m_tempDir.path() + "/temp_image");
QVERIFY(ok);
QVERIFY(!pixmap.isNull());
QVERIFY(pixmap.depth() > 1);
QVERIFY(!pixmap.isQBitmap());
// The do the same check for bitmaps..
QBitmap bitmap("temp_image.png");
QBitmap bitmap(m_tempDir.path() + "/temp_image.png");
QVERIFY(!bitmap.isNull());
QCOMPARE(bitmap.depth(), 1);
QVERIFY(bitmap.isQBitmap());
bitmap = QBitmap();
ok = bitmap.load("temp_image.png");
ok = bitmap.load(m_tempDir.path() + "/temp_image.png");
QVERIFY(ok);
QVERIFY(!bitmap.isNull());
QCOMPARE(bitmap.depth(), 1);

View File

@ -134,6 +134,7 @@ private slots:
void xToCursorForLigatures();
void cursorInNonStopChars();
void nbsp();
void nbspWithFormat();
void noModificationOfInputString();
void superscriptCrash_qtbug53911();
@ -2254,5 +2255,41 @@ void tst_QTextLayout::superscriptCrash_qtbug53911()
qDeleteAll(textLayouts);
}
void tst_QTextLayout::nbspWithFormat()
{
QString s1 = QLatin1String("ABCDEF ");
QString s2 = QLatin1String("GHI");
QChar nbsp(QChar::Nbsp);
QString s3 = QLatin1String("JKLMNOPQRSTUVWXYZ");
QTextLayout layout;
layout.setText(s1 + s2 + nbsp + s3);
QTextLayout::FormatRange formatRange;
formatRange.start = s1.length() + s2.length();
formatRange.length = 1;
formatRange.format.setFontUnderline(true);
QList<QTextLayout::FormatRange> overrides;
overrides.append(formatRange);
layout.setAdditionalFormats(overrides);
layout.beginLayout();
forever {
QTextLine line = layout.createLine();
if (!line.isValid())
break;
line.setLineWidth(1);
}
layout.endLayout();
QCOMPARE(layout.lineCount(), 2);
QCOMPARE(layout.lineAt(0).textStart(), 0);
QCOMPARE(layout.lineAt(0).textLength(), s1.length());
QCOMPARE(layout.lineAt(1).textStart(), s1.length());
QCOMPARE(layout.lineAt(1).textLength(), s2.length() + 1 + s3.length());
}
QTEST_MAIN(tst_QTextLayout)
#include "tst_qtextlayout.moc"

View File

@ -1120,8 +1120,8 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
QTest::newRow("$$section(): bad number of arguments")
<< "VAR = $$section(1, 2) \\\n$$section(1, 2, 3, 4, 5)"
<< "VAR ="
<< "##:1: section(var) section(var, sep, begin, end) requires three or four arguments.\n"
"##:2: section(var) section(var, sep, begin, end) requires three or four arguments."
<< "##:1: section(var, sep, begin, end) requires three or four arguments.\n"
"##:2: section(var, sep, begin, end) requires three or four arguments."
<< true;
QTest::newRow("$$find()")

View File

@ -1093,6 +1093,10 @@ static QSet<QString> fileListUnderIndex(const QFileSystemModel *model, const QMo
void tst_QFileSystemModel::specialFiles()
{
#ifndef Q_OS_UNIX
QSKIP("Not implemented");
#endif
QFileSystemModel model;
model.setFilter(QDir::AllEntries | QDir::System | QDir::Hidden);
@ -1101,23 +1105,8 @@ void tst_QFileSystemModel::specialFiles()
// as it will always return a valid index for existing files,
// even if the file is not visible with the given filter.
#if defined(Q_OS_UNIX)
const QModelIndex rootIndex = model.setRootPath(QStringLiteral("/dev/"));
const QString testFileName = QStringLiteral("null");
#elif defined(Q_OS_WIN)
const QModelIndex rootIndex = model.setRootPath(flatDirTestPath);
const QString testFileName = QStringLiteral("linkSource.lnk");
QFile file(flatDirTestPath + QLatin1String("/linkTarget.txt"));
QVERIFY(file.open(QIODevice::WriteOnly));
file.close();
QVERIFY(file.link(flatDirTestPath + '/' + testFileName));
#else
QSKIP("Not implemented");
QModelIndex rootIndex;
QString testFileName;
#endif
QTRY_VERIFY(fileListUnderIndex(&model, rootIndex).contains(testFileName));

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

View File

@ -96,6 +96,9 @@ private Q_SLOTS:
void taskQTBUG_7902_contextMenuCrash();
#endif
void taskQTBUG_48157_dprPixmap();
void taskQTBUG_48157_dprMovie();
private:
QLabel *testWidget;
QPointer<Widget> test_box;
@ -541,5 +544,26 @@ void tst_QLabel::taskQTBUG_7902_contextMenuCrash()
}
#endif
void tst_QLabel::taskQTBUG_48157_dprPixmap()
{
QLabel label;
QPixmap pixmap;
pixmap.load(QFINDTESTDATA(QStringLiteral("red@2x.png")));
QCOMPARE(pixmap.devicePixelRatio(), 2.0);
label.setPixmap(pixmap);
QCOMPARE(label.sizeHint(), pixmap.rect().size() / pixmap.devicePixelRatio());
}
void tst_QLabel::taskQTBUG_48157_dprMovie()
{
QLabel label;
QMovie movie;
movie.setFileName(QFINDTESTDATA(QStringLiteral("red@2x.png")));
movie.start();
QCOMPARE(movie.currentPixmap().devicePixelRatio(), 2.0);
label.setMovie(&movie);
QCOMPARE(label.sizeHint(), movie.currentPixmap().size() / movie.currentPixmap().devicePixelRatio());
}
QTEST_MAIN(tst_QLabel)
#include "tst_qlabel.moc"

View File

@ -0,0 +1,6 @@
TEMPLATE = app
TARGET = childwidget
INCLUDEPATH += .
QT += widgets
SOURCES += main.cpp

View File

@ -0,0 +1,92 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtWidgets>
class CursorWidget : public QWidget
{
public:
CursorWidget(QCursor cursor, QColor color)
:m_cursor(cursor)
,m_color(color)
{
if (cursor.shape() == Qt::ArrowCursor)
unsetCursor();
else
setCursor(cursor);
}
void paintEvent(QPaintEvent *e)
{
QPainter p(this);
p.fillRect(e->rect(), m_color);
}
void mousePressEvent(QMouseEvent *)
{
// Toggle cursor
QCursor newCursor = (cursor().shape() == m_cursor.shape()) ? QCursor() : m_cursor;
if (newCursor.shape() == Qt::ArrowCursor)
unsetCursor();
else
setCursor(newCursor);
}
private:
QCursor m_cursor;
QColor m_color;
};
int main(int argc, char **argv)
{
QApplication app(argc, argv);
// Test child widgets (one of which is native) with set cursors.
// Click window to toggle cursor.
CursorWidget w1((QCursor(Qt::SizeVerCursor)), QColor(Qt::blue).darker());
w1.resize(200, 200);
w1.show();
CursorWidget w2((QCursor(Qt::OpenHandCursor)), QColor(Qt::red).darker());
w2.setParent(&w1);
w2.setGeometry(0, 0, 100, 100);
w2.show();
CursorWidget w3((QCursor(Qt::IBeamCursor)), QColor(Qt::green).darker());
w3.winId();
w3.setParent(&w1);
w3.setGeometry(100, 100, 100, 100);
w3.show();
return app.exec();
}

View File

@ -0,0 +1,5 @@
TEMPLATE = app
TARGET = childwindow
INCLUDEPATH += .
SOURCES += main.cpp

View File

@ -0,0 +1,91 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtGui>
class CursorWindow : public QRasterWindow
{
public:
CursorWindow(QCursor cursor, QColor color)
:m_cursor(cursor)
,m_color(color)
{
if (cursor.shape() == Qt::ArrowCursor)
unsetCursor();
else
setCursor(cursor);
}
void paintEvent(QPaintEvent *e)
{
QPainter p(this);
p.fillRect(e->rect(), m_color);
}
void mousePressEvent(QMouseEvent *)
{
// Toggle cursor
QCursor newCursor = (cursor().shape() == m_cursor.shape()) ? QCursor() : m_cursor;
if (newCursor.shape() == Qt::ArrowCursor)
unsetCursor();
else
setCursor(newCursor);
}
private:
QCursor m_cursor;
QColor m_color;
};
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
// Test child windows with set cursors. Create parent window and
// two child windows. Click window to toggle cursor.
CursorWindow w1((QCursor(Qt::SizeVerCursor)), QColor(Qt::blue).darker());
w1.resize(200, 200);
w1.show();
CursorWindow w2((QCursor(Qt::OpenHandCursor)), QColor(Qt::red).darker());
w2.setParent(&w1);
w2.setGeometry(0, 0, 100, 100);
w2.show();
CursorWindow w3((QCursor(Qt::IBeamCursor)), QColor(Qt::green).darker());
w3.setParent(&w1);
w3.setGeometry(100, 100, 100, 100);
w3.show();
return app.exec();
}

View File

@ -0,0 +1,6 @@
TEMPLATE = app
TARGET = childwindowcontainer
INCLUDEPATH += .
QT += widgets
SOURCES += main.cpp

View File

@ -0,0 +1,138 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtWidgets>
class CursorWindow : public QRasterWindow
{
public:
CursorWindow(QCursor cursor, QColor color)
:m_cursor(cursor)
,m_color(color)
{
if (cursor.shape() == Qt::ArrowCursor)
unsetCursor();
else
setCursor(cursor);
}
void paintEvent(QPaintEvent *e)
{
QPainter p(this);
p.fillRect(e->rect(), m_color);
}
void mousePressEvent(QMouseEvent *)
{
// Toggle cursor
QCursor newCursor = (cursor().shape() == m_cursor.shape()) ? QCursor() : m_cursor;
if (newCursor.shape() == Qt::ArrowCursor)
unsetCursor();
else
setCursor(newCursor);
}
private:
QCursor m_cursor;
QColor m_color;
};
class CursorWidget : public QWidget
{
public:
CursorWidget(QCursor cursor, QColor color)
:m_cursor(cursor)
,m_color(color)
{
if (cursor.shape() == Qt::ArrowCursor)
unsetCursor();
else
setCursor(cursor);
}
void paintEvent(QPaintEvent *e)
{
QPainter p(this);
p.fillRect(e->rect(), m_color);
}
void mousePressEvent(QMouseEvent *)
{
// Toggle cursor
QCursor newCursor = (cursor().shape() == m_cursor.shape()) ? QCursor() : m_cursor;
if (newCursor.shape() == Qt::ArrowCursor)
unsetCursor();
else
setCursor(newCursor);
}
private:
QCursor m_cursor;
QColor m_color;
};
int main(int argc, char **argv)
{
QApplication app(argc, argv);
{
// Create top-level windowContainer with window. Setting the cursor
// for the container should set the cursor for the window as well.
// Setting the cursor for the window overrides the cursor for the
// container. The example starts out with a window cursor; click
// to fall back to the container cursor.
CursorWindow *w1 = new CursorWindow(QCursor(Qt::OpenHandCursor), QColor(Qt::red).darker());
QWidget* container = QWidget::createWindowContainer(w1);
container->resize(200, 200);
container->setCursor(Qt::PointingHandCursor);
container->show();
}
{
// Similar to above, but with a top-level QWiget
CursorWidget *w1 = new CursorWidget(QCursor(Qt::IBeamCursor), QColor(Qt::green).darker());
w1->resize(200, 200);
CursorWindow *w2 = new CursorWindow(QCursor(Qt::OpenHandCursor), QColor(Qt::red).darker());
QWidget* container = QWidget::createWindowContainer(w2);
container->winId(); // must make the container native, otherwise setCursor
// sets the cursor on a QWindowContainerClassWindow which
// is outside the QWindow hierarchy (macOS).
container->setParent(w1);
container->setCursor(Qt::PointingHandCursor);
container->setGeometry(0, 0, 100, 100);
w1->show();
}
return app.exec();
}

View File

@ -1,3 +1,3 @@
TEMPLATE = subdirs
SUBDIRS = allcursors grab_override qcursorhighdpi
SUBDIRS = allcursors childwidget childwindow childwindowcontainer grab_override qcursorhighdpi