Merge "Merge remote-tracking branch 'origin/5.6' into dev" into refs/staging/dev

This commit is contained in:
Liang Qi 2015-11-23 19:17:25 +00:00 committed by The Qt Project
commit 746f54c6df
71 changed files with 1185 additions and 591 deletions

View File

@ -43,8 +43,5 @@
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name=\"internetClient\" />
</Capabilities>
$${WINRT_MANIFEST.capabilities}
</Package>

View File

@ -89,7 +89,7 @@ for(ever) {
MODULE_LIBS_ADD -= $$QMAKE_DEFAULT_LIBDIRS
LINKAGE =
mac:contains(MODULE_CONFIG, lib_bundle) {
contains(MODULE_CONFIG, lib_bundle) {
FRAMEWORK_INCLUDE = $${MODULE_LIBS}/$${MODULE_NAME}.framework/Headers
!qt_no_framework_direct_includes {
INCLUDEPATH *= $$FRAMEWORK_INCLUDE
@ -111,7 +111,7 @@ for(ever) {
# Re-insert the major version in the library name (cf qt5LibraryTarget above)
# unless it's a framework build
!mac|!contains(MODULE_CONFIG, lib_bundle): \
!contains(MODULE_CONFIG, lib_bundle): \
MODULE_NAME ~= s,^Qt,Qt$$QT_MAJOR_VERSION,
isEmpty(LINKAGE) {

View File

@ -15,7 +15,7 @@ defineReplace(qtPlatformTargetSuffix) {
defineReplace(qtLibraryTarget) {
LIBRARY_NAME = $$1
mac:CONFIG(shared, static|shared):contains(QT_CONFIG, qt_framework) {
CONFIG(shared, static|shared):contains(QT_CONFIG, qt_framework) {
QMAKE_FRAMEWORK_BUNDLE_NAME = $$LIBRARY_NAME
export(QMAKE_FRAMEWORK_BUNDLE_NAME)
}

View File

@ -42,8 +42,8 @@ host_build {
}
}
mac:CONFIG(shared, static|shared):contains(QT_CONFIG, qt_framework): \
CONFIG += qt_framework
CONFIG(shared, static|shared):contains(QT_CONFIG, qt_framework): \
CONFIG += lib_bundle
CONFIG += relative_qt_rpath # Qt libraries should be relocatable
@ -106,7 +106,7 @@ else: \
DEFINES += QT_BUILD_$${ucmodule}_LIB
# OS X and iOS frameworks
qt_framework {
lib_bundle {
# Set the CFBundleIdentifier prefix for Qt frameworks
QMAKE_TARGET_BUNDLE_PREFIX = org.qt-project
#QMAKE_FRAMEWORK_VERSION = 4.0
@ -115,8 +115,6 @@ qt_framework {
CONFIG += bundle
QMAKE_BUNDLE_EXTENSION = .framework
QMAKE_INFO_PLIST = $$QMAKESPEC/Info.plist.lib
} else {
CONFIG += lib_bundle
}
CONFIG -= qt_install_headers #no need to install these as well
!debug_and_release|!build_all|CONFIG(release, debug|release) {
@ -239,7 +237,7 @@ load(qt_installs)
load(qt_targets)
# this builds on top of qt_common
!internal_module:!qt_framework:if(unix|mingw) {
!internal_module:!lib_bundle:if(unix|mingw) {
CONFIG += create_pc
QMAKE_PKGCONFIG_DESTDIR = pkgconfig
host_build: \

View File

@ -55,7 +55,7 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri
module_rundep =
static: \
module_build_type = staticlib
else: qt_framework: \
else: lib_bundle: \
module_build_type = lib_bundle
else: \
module_build_type =

View File

@ -27,7 +27,7 @@ check.commands += $(TESTRUNNER)
unix {
isEmpty(TEST_TARGET_DIR): TEST_TARGET_DIR = .
mac:app_bundle: \
app_bundle: \
check.commands += $${TEST_TARGET_DIR}/$(QMAKE_TARGET).app/Contents/MacOS/$(QMAKE_TARGET)
else: \
check.commands += $${TEST_TARGET_DIR}/$(QMAKE_TARGET)

View File

@ -108,6 +108,10 @@
INDENT = "$$escape_expand(\\r\\n) "
# All Windows 10 applications need to have internetClient. It is also not marked as additional
# capability anymore and is assumed to be standard.
*-msvc2015: WINRT_MANIFEST.capabilities += internetClient
# Capabilities are given as a string list and may change with the configuration (network, sensors, etc.)
WINRT_MANIFEST.capabilities = $$unique(WINRT_MANIFEST.capabilities)
WINRT_MANIFEST.capabilities_device = $$unique(WINRT_MANIFEST.capabilities_device)

View File

@ -56,6 +56,7 @@
QT_BEGIN_NAMESPACE
// FIXME: a line ending in CRLF gets counted as two lines.
#if 1
#define qmake_endOfLine(c) (c == '\r' || c == '\n')
#else
@ -431,104 +432,103 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
char *inc = 0;
if(file->type == QMakeSourceFileInfo::TYPE_UI) {
// skip whitespaces
while(x < buffer_len && (*(buffer+x) == ' ' || *(buffer+x) == '\t'))
while (x < buffer_len && (buffer[x] == ' ' || buffer[x] == '\t'))
++x;
if(*(buffer + x) == '<') {
if (buffer[x] == '<') {
++x;
if(buffer_len >= x + 12 && !strncmp(buffer + x, "includehint", 11) &&
(*(buffer + x + 11) == ' ' || *(buffer + x + 11) == '>')) {
for(x += 11; *(buffer + x) != '>'; ++x) ;
if (buffer_len >= x + 12 && !strncmp(buffer + x, "includehint", 11) &&
(buffer[x + 11] == ' ' || buffer[x + 11] == '>')) {
for (x += 11; buffer[x] != '>'; ++x) {} // skip
int inc_len = 0;
for(x += 1 ; *(buffer + x + inc_len) != '<'; ++inc_len) ;
*(buffer + x + inc_len) = '\0';
for (x += 1 ; buffer[x + inc_len] != '<'; ++inc_len) {} // skip
buffer[x + inc_len] = '\0';
inc = buffer + x;
} else if(buffer_len >= x + 13 && !strncmp(buffer + x, "customwidget", 12) &&
(*(buffer + x + 12) == ' ' || *(buffer + x + 12) == '>')) {
for(x += 13; *(buffer + x) != '>'; ++x) ; //skip up to >
} else if (buffer_len >= x + 13 && !strncmp(buffer + x, "customwidget", 12) &&
(buffer[x + 12] == ' ' || buffer[x + 12] == '>')) {
for (x += 13; buffer[x] != '>'; ++x) {} // skip up to >
while(x < buffer_len) {
for(x++; *(buffer + x) != '<'; ++x) ; //skip up to <
for (x++; buffer[x] != '<'; ++x) {} // skip up to <
x++;
if(buffer_len >= x + 7 && !strncmp(buffer+x, "header", 6) &&
(*(buffer + x + 6) == ' ' || *(buffer + x + 6) == '>')) {
for(x += 7; *(buffer + x) != '>'; ++x) ; //skip up to >
(buffer[x + 6] == ' ' || buffer[x + 6] == '>')) {
for (x += 7; buffer[x] != '>'; ++x) {} // skip up to >
int inc_len = 0;
for(x += 1 ; *(buffer + x + inc_len) != '<'; ++inc_len) ;
*(buffer + x + inc_len) = '\0';
for (x += 1 ; buffer[x + inc_len] != '<'; ++inc_len) {} // skip
buffer[x + inc_len] = '\0';
inc = buffer + x;
break;
} else if(buffer_len >= x + 14 && !strncmp(buffer+x, "/customwidget", 13) &&
(*(buffer + x + 13) == ' ' || *(buffer + x + 13) == '>')) {
(buffer[x + 13] == ' ' || buffer[x + 13] == '>')) {
x += 14;
break;
}
}
} else if(buffer_len >= x + 8 && !strncmp(buffer + x, "include", 7) &&
(*(buffer + x + 7) == ' ' || *(buffer + x + 7) == '>')) {
for(x += 8; *(buffer + x) != '>'; ++x) {
if(buffer_len >= x + 9 && *(buffer + x) == 'i' &&
(buffer[x + 7] == ' ' || buffer[x + 7] == '>')) {
for (x += 8; buffer[x] != '>'; ++x) {
if (buffer_len >= x + 9 && buffer[x] == 'i' &&
!strncmp(buffer + x, "impldecl", 8)) {
for(x += 8; *(buffer + x) != '='; ++x) ;
if(*(buffer + x) != '=')
for (x += 8; buffer[x] != '='; ++x) {} // skip
if (buffer[x] != '=')
continue;
for(++x; *(buffer+x) == '\t' || *(buffer+x) == ' '; ++x) ;
for (++x; buffer[x] == '\t' || buffer[x] == ' '; ++x) {} // skip
char quote = 0;
if(*(buffer+x) == '\'' || *(buffer+x) == '"') {
quote = *(buffer + x);
if (buffer[x] == '\'' || buffer[x] == '"') {
quote = buffer[x];
++x;
}
int val_len;
for(val_len = 0; true; ++val_len) {
if(quote) {
if(*(buffer+x+val_len) == quote)
if (buffer[x + val_len] == quote)
break;
} else if(*(buffer + x + val_len) == '>' ||
*(buffer + x + val_len) == ' ') {
} else if (buffer[x + val_len] == '>' ||
buffer[x + val_len] == ' ') {
break;
}
}
//? char saved = *(buffer + x + val_len);
*(buffer + x + val_len) = '\0';
//? char saved = buffer[x + val_len];
buffer[x + val_len] = '\0';
if(!strcmp(buffer+x, "in implementation")) {
//### do this
}
}
}
int inc_len = 0;
for(x += 1 ; *(buffer + x + inc_len) != '<'; ++inc_len) ;
*(buffer + x + inc_len) = '\0';
for (x += 1 ; buffer[x + inc_len] != '<'; ++inc_len) {} // skip
buffer[x + inc_len] = '\0';
inc = buffer + x;
}
}
//read past new line now..
for(; x < buffer_len && !qmake_endOfLine(*(buffer + x)); ++x) ;
for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip
++line_count;
} else if(file->type == QMakeSourceFileInfo::TYPE_QRC) {
} else if(file->type == QMakeSourceFileInfo::TYPE_C) {
for(int beginning=1; x < buffer_len; ++x) {
// whitespace comments and line-endings
// Seek code or directive, skipping comments and space:
for(; x < buffer_len; ++x) {
if(*(buffer+x) == ' ' || *(buffer+x) == '\t') {
if (buffer[x] == ' ' || buffer[x] == '\t') {
// keep going
} else if(*(buffer+x) == '/') {
} else if (buffer[x] == '/' && x + 1 < buffer_len &&
(buffer[x + 1] == '/' || buffer[x + 1] == '*')) {
++x;
if(buffer_len >= x) {
if(*(buffer+x) == '/') { //c++ style comment
for(; x < buffer_len && !qmake_endOfLine(*(buffer + x)); ++x) ;
if (buffer[x] == '/') { // C++-style comment
for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip
beginning = 1;
} else if(*(buffer+x) == '*') { //c style comment
for(++x; x < buffer_len; ++x) {
if(*(buffer+x) == '*') {
if(x+1 < buffer_len && *(buffer + (x+1)) == '/') {
++x;
} else { // C-style comment
while (++x < buffer_len) {
if (buffer[x] == '*') {
if (x + 1 < buffer_len && buffer[x + 1] == '/') {
++x; // skip '*'; for loop skips '/'.
break;
}
} else if(qmake_endOfLine(*(buffer+x))) {
} else if (qmake_endOfLine(buffer[x])) {
++line_count;
}
}
}
}
} else if(qmake_endOfLine(*(buffer+x))) {
} else if (qmake_endOfLine(buffer[x])) {
++line_count;
beginning = 1;
} else {
@ -540,19 +540,29 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
break;
// preprocessor directive
if(beginning && *(buffer+x) == '#')
if (beginning && buffer[x] == '#') {
// Advance to start of preprocessing directive
while (++x < buffer_len
&& (buffer[x] == ' ' || buffer[x] == '\t')) {} // skip
if (qmake_endOfLine(buffer[x])) {
++line_count;
beginning = 1;
continue;
}
break;
}
// quoted strings
if(*(buffer+x) == '\'' || *(buffer+x) == '"') {
const char term = *(buffer+(x++));
for(; x < buffer_len; ++x) {
if(*(buffer+x) == term) {
if (buffer[x] == '\'' || buffer[x] == '"') {
const char term = buffer[x];
while (++x < buffer_len) {
if (buffer[x] == term) {
++x;
break;
} else if(*(buffer+x) == '\\') {
} else if (buffer[x] == '\\') {
++x;
} else if(qmake_endOfLine(*(buffer+x))) {
} else if (qmake_endOfLine(buffer[x])) {
++line_count;
}
}
@ -562,34 +572,23 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
if(x >= buffer_len)
break;
//got a preprocessor symbol
++x;
while(x < buffer_len) {
if(*(buffer+x) != ' ' && *(buffer+x) != '\t')
break;
++x;
}
// Got a preprocessor directive
const char *const keyword = buffer + x;
for (;
x < buffer_len && buffer[x] >= 'a' && buffer[x] <= 'z';
x++) {} // skip over identifier
int keyword_len = buffer + x - keyword;
for (;
x < buffer_len && (buffer[x] == ' ' || buffer[x] == '\t');
x++) {} // skip spaces after keyword
int keyword_len = 0;
const char *keyword = buffer+x;
while(x+keyword_len < buffer_len) {
if(((*(buffer+x+keyword_len) < 'a' || *(buffer+x+keyword_len) > 'z')) &&
*(buffer+x+keyword_len) != '_') {
for(x+=keyword_len; //skip spaces after keyword
x < buffer_len && (*(buffer+x) == ' ' || *(buffer+x) == '\t');
x++) ;
break;
} else if(qmake_endOfLine(*(buffer+x+keyword_len))) {
x += keyword_len-1;
/* Keyword with nothing after it, e.g. #endif: not interesting. */
if (qmake_endOfLine(buffer[x]))
keyword_len = 0;
break;
}
keyword_len++;
}
if((keyword_len == 7 && !strncmp(keyword, "include", 7)) // C & Obj-C
|| (keyword_len == 6 && !strncmp(keyword, "import", 6))) { // Obj-C
char term = *(buffer + x);
char term = buffer[x];
if(term == '<') {
try_local = false;
term = '>';
@ -599,34 +598,21 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
x++;
int inc_len;
for(inc_len = 0; *(buffer + x + inc_len) != term && !qmake_endOfLine(*(buffer + x + inc_len)); ++inc_len) ;
*(buffer + x + inc_len) = '\0';
for (inc_len = 0;
buffer[x + inc_len] != term && !qmake_endOfLine(buffer[x + inc_len]);
++inc_len) {} // skip until end of include name
buffer[x + inc_len] = '\0';
inc = buffer + x;
x += inc_len;
} else if(keyword_len == 13 && !strncmp(keyword, "qmake_warning", keyword_len)) {
char term = 0;
if(*(buffer + x) == '"')
term = '"';
if(*(buffer + x) == '\'')
term = '\'';
if(term)
x++;
int msg_len;
for(msg_len = 0; (term && *(buffer + x + msg_len) != term) &&
!qmake_endOfLine(*(buffer + x + msg_len)); ++msg_len) ;
*(buffer + x + msg_len) = '\0';
debug_msg(0, "%s:%d %s -- %s", file->file.local().toLatin1().constData(), line_count, keyword, buffer+x);
x += msg_len;
} else if(*(buffer+x) == '\'' || *(buffer+x) == '"') {
const char term = *(buffer+(x++));
} else if (buffer[x] == '\'' || buffer[x] == '"') {
const char term = buffer[x++];
while(x < buffer_len) {
if(*(buffer+x) == term)
if (buffer[x] == term)
break;
if(*(buffer+x) == '\\') {
if (buffer[x] == '\\') {
x+=2;
} else {
if(qmake_endOfLine(*(buffer+x)))
if (qmake_endOfLine(buffer[x]))
++line_count;
++x;
}
@ -702,6 +688,13 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
return true;
}
static bool isCWordChar(char c) {
return c == '_'
|| (c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9');
}
bool QMakeSourceFileInfo::findMocs(SourceFile *file)
{
if(file->moc_checked)
@ -739,14 +732,14 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
/* qmake ignore Q_GADGET */
/* qmake ignore Q_OBJECT */
for(int x = 0; x < buffer_len; x++) {
if(*(buffer + x) == '/') {
if (buffer[x] == '/') {
++x;
if(buffer_len >= x) {
if(*(buffer + x) == '/') { //c++ style comment
for(;x < buffer_len && !qmake_endOfLine(*(buffer + x)); ++x) ;
} else if(*(buffer + x) == '*') { //c style comment
if (buffer[x] == '/') { // C++-style comment
for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip
} else if (buffer[x] == '*') { // C-style comment
for(++x; x < buffer_len; ++x) {
if(*(buffer + x) == 't' || *(buffer + x) == 'q') { //ignore
if (buffer[x] == 't' || buffer[x] == 'q') { // ignore
if(buffer_len >= (x + 20) &&
!strncmp(buffer + x + 1, "make ignore Q_OBJECT", 20)) {
debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_OBJECT\"",
@ -760,38 +753,35 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
x += 20;
ignore_qgadget = true;
}
} else if(*(buffer + x) == '*') {
if(buffer_len >= (x+1) && *(buffer + (x+1)) == '/') {
} else if (buffer[x] == '*') {
if (buffer_len >= x + 1 && buffer[x + 1] == '/') {
++x;
break;
}
} else if(Option::debug_level && qmake_endOfLine(*(buffer + x))) {
} else if (Option::debug_level && qmake_endOfLine(buffer[x])) {
++line_count;
}
}
}
}
} else if(*(buffer+x) == '\'' || *(buffer+x) == '"') {
const char term = *(buffer+(x++));
} else if (buffer[x] == '\'' || buffer[x] == '"') {
const char term = buffer[x++];
while(x < buffer_len) {
if(*(buffer+x) == term)
if (buffer[x] == term)
break;
if(*(buffer+x) == '\\') {
if (buffer[x] == '\\') {
x+=2;
} else {
if(qmake_endOfLine(*(buffer+x)))
if (qmake_endOfLine(buffer[x]))
++line_count;
++x;
}
}
}
if(Option::debug_level && qmake_endOfLine(*(buffer+x)))
if (Option::debug_level && qmake_endOfLine(buffer[x]))
++line_count;
if (buffer_len > x + 2 && buffer[x + 1] == 'Q' && buffer[x + 2] == '_' &&
*(buffer + x) != '_' &&
(*(buffer + x) < 'a' || *(buffer + x) > 'z') &&
(*(buffer + x) < 'A' || *(buffer + x) > 'Z') &&
(*(buffer + x) < '0' || *(buffer + x) > '9')) {
if (buffer_len > x + 2 && buffer[x + 1] == 'Q' &&
buffer[x + 2] == '_' && !isCWordChar(buffer[x])) {
++x;
int match = 0;
static const char *interesting[] = { "OBJECT", "GADGET" };
@ -800,8 +790,8 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
continue;
else if(interest == 1 && ignore_qgadget)
continue;
for(m1 = 0, m2 = 0; *(interesting[interest]+m1); ++m1) {
if(*(interesting[interest]+m1) != *(buffer+x+2+m1)) {
for (m1 = 0, m2 = 0; interesting[interest][m1]; ++m1) {
if (interesting[interest][m1] != buffer[x + 2 + m1]) {
m2 = -1;
break;
}
@ -812,14 +802,12 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
break;
}
}
if(match && *(buffer+x+match) != '_' &&
(*(buffer+x+match) < 'a' || *(buffer+x+match) > 'z') &&
(*(buffer+x+match) < 'A' || *(buffer+x+match) > 'Z') &&
(*(buffer+x+match) < '0' || *(buffer+x+match) > '9')) {
if(Option::debug_level) {
*(buffer+x+match) = '\0';
debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s", file->file.real().toLatin1().constData(),
line_count, buffer+x);
if (match && !isCWordChar(buffer[x + match])) {
if (Option::debug_level) {
buffer[x + match] = '\0';
debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s",
file->file.real().toLatin1().constData(),
line_count, buffer + x);
}
file->mocable = true;
return true;

View File

@ -67,5 +67,9 @@ contains(QT_CONFIG, system-zlib) {
DEFINES += FT_CONFIG_OPTION_SYSTEM_ZLIB
include($$PWD/../zlib_dependency.pri)
}
contains(QT_CONFIG, system-png) {
DEFINES += FT_CONFIG_OPTION_USE_PNG
include($$PWD/../png_dependency.pri)
}
DEFINES += TT_CONFIG_OPTION_SUBPIXEL_HINTING

View File

@ -66,9 +66,13 @@
#ifndef QT_NO_QOBJECT
#if defined(Q_OS_UNIX)
# if defined(Q_OS_OSX)
# include "qeventdispatcher_cf_p.h"
# else
# if !defined(QT_NO_GLIB)
# include "qeventdispatcher_glib_p.h"
# endif
# endif
# include "qeventdispatcher_unix_p.h"
#endif
#ifdef Q_OS_WIN
@ -469,12 +473,21 @@ void QCoreApplicationPrivate::createEventDispatcher()
{
Q_Q(QCoreApplication);
#if defined(Q_OS_UNIX)
# if !defined(QT_NO_GLIB)
# if defined(Q_OS_OSX)
bool ok = false;
int value = qEnvironmentVariableIntValue("QT_EVENT_DISPATCHER_CORE_FOUNDATION", &ok);
if (ok && value > 0)
eventDispatcher = new QEventDispatcherCoreFoundation(q);
else
eventDispatcher = new QEventDispatcherUNIX(q);
# elif !defined(QT_NO_GLIB)
if (qEnvironmentVariableIsEmpty("QT_NO_GLIB") && QEventDispatcherGlib::versionSupported())
eventDispatcher = new QEventDispatcherGlib(q);
else
# endif
eventDispatcher = new QEventDispatcherUNIX(q);
# else
eventDispatcher = new QEventDispatcherUNIX(q);
# endif
#elif defined(Q_OS_WINRT)
eventDispatcher = new QEventDispatcherWinRT(q);
#elif defined(Q_OS_WIN)
@ -613,8 +626,9 @@ void QCoreApplicationPrivate::initLocale()
The command line arguments which are passed to QCoreApplication's
constructor should be accessed using the arguments() function.
Note that some arguments supplied by the user may have been
processed and removed by QCoreApplication.
\note QCoreApplication removes option \c -qmljsdebugger="...". It parses the
argument of \c qmljsdebugger, and then removes this option plus its argument.
For more advanced command line option handling, create a QCommandLineParser.

View File

@ -49,6 +49,8 @@
# include <UIKit/UIApplication.h>
#endif
QT_USE_NAMESPACE
@interface RunLoopModeTracker : NSObject {
QStack<CFStringRef> m_runLoopModes;
}
@ -119,7 +121,6 @@ static CFStringRef runLoopMode(NSDictionary *dictionary)
@end
QT_BEGIN_NAMESPACE
QT_USE_NAMESPACE
class RunLoopDebugger : public QObject
{

View File

@ -578,11 +578,8 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
QString mainPattern;
const QString preferredLanguage = QLocale::system().name();
QListIterator<QString> mimeFilesIter(mimeFiles);
mimeFilesIter.toBack();
while (mimeFilesIter.hasPrevious()) { // global first, then local.
const QString fullPath = mimeFilesIter.previous();
QFile qfile(fullPath);
for (QStringList::const_reverse_iterator it = mimeFiles.crbegin(), end = mimeFiles.crend(); it != end; ++it) { // global first, then local.
QFile qfile(*it);
if (!qfile.open(QFile::ReadOnly))
continue;

View File

@ -54,7 +54,9 @@ namespace {
// avoid duplicate QStringLiteral data:
inline QString iidKeyLiteral() { return QStringLiteral("IID"); }
#ifdef QT_SHARED
inline QString versionKeyLiteral() { return QStringLiteral("version"); }
#endif
inline QString metaDataKeyLiteral() { return QStringLiteral("MetaData"); }
inline QString keysKeyLiteral() { return QStringLiteral("Keys"); }

View File

@ -36,9 +36,14 @@
#include "qplatformdefs.h"
#include <private/qcoreapplication_p.h>
#include <private/qcore_unix_p.h>
#if !defined(QT_NO_GLIB)
#if defined(Q_OS_OSX)
# include <private/qeventdispatcher_cf_p.h>
#else
# if !defined(QT_NO_GLIB)
# include "../kernel/qeventdispatcher_glib_p.h"
# endif
#endif
#include <private/qeventdispatcher_unix_p.h>
@ -243,14 +248,23 @@ typedef void*(*QtThreadCallback)(void*);
void QThreadPrivate::createEventDispatcher(QThreadData *data)
{
#if !defined(QT_NO_GLIB)
#if defined(Q_OS_OSX)
bool ok = false;
int value = qEnvironmentVariableIntValue("QT_EVENT_DISPATCHER_CORE_FOUNDATION", &ok);
if (ok && value > 0)
data->eventDispatcher.storeRelease(new QEventDispatcherCoreFoundation);
else
data->eventDispatcher.storeRelease(new QEventDispatcherUNIX);
#elif !defined(QT_NO_GLIB)
if (qEnvironmentVariableIsEmpty("QT_NO_GLIB")
&& qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB")
&& QEventDispatcherGlib::versionSupported())
data->eventDispatcher.storeRelease(new QEventDispatcherGlib);
else
#endif
data->eventDispatcher.storeRelease(new QEventDispatcherUNIX);
#else
data->eventDispatcher.storeRelease(new QEventDispatcherUNIX);
#endif
data->eventDispatcher.load()->startingUp();
}

View File

@ -48,6 +48,8 @@
#endif
#ifdef Q_OS_WINRT
#include <qfunctions_winrt.h>
#include <wrl.h>
#include <windows.foundation.h>
#include <windows.foundation.collections.h>
@ -644,21 +646,53 @@ QVariant QSystemLocalePrivate::uiLanguages()
}
ComPtr<ABI::Windows::Foundation::Collections::IVectorView<HSTRING> > languageList;
appLanguagesStatics->get_ManifestLanguages(&languageList);
if (!languageList)
return QStringList();
// Languages is a ranked list of "long names" (e.g. en-US) of preferred languages, which matches
// languages from the manifest with languages from the user's system.
HRESULT hr = appLanguagesStatics->get_Languages(&languageList);
Q_ASSERT_SUCCEEDED(hr);
unsigned int size;
languageList->get_Size(&size);
hr = languageList->get_Size(&size);
Q_ASSERT_SUCCEEDED(hr);
result.reserve(size);
for (unsigned int i = 0; i < size; ++i) {
HString language;
languageList->GetAt(i, language.GetAddressOf());
hr = languageList->GetAt(i, language.GetAddressOf());
Q_ASSERT_SUCCEEDED(hr);
UINT32 length;
PCWSTR rawString = language.GetRawBuffer(&length);
result << QString::fromWCharArray(rawString, length);
}
// ManifestLanguages covers all languages given in the manifest and uses short names (like "en").
hr = appLanguagesStatics->get_ManifestLanguages(&languageList);
Q_ASSERT_SUCCEEDED(hr);
hr = languageList->get_Size(&size);
Q_ASSERT_SUCCEEDED(hr);
for (unsigned int i = 0; i < size; ++i) {
HString language;
hr = languageList->GetAt(i, language.GetAddressOf());
Q_ASSERT_SUCCEEDED(hr);
UINT32 length;
PCWSTR rawString = language.GetRawBuffer(&length);
const QString qLanguage = QString::fromWCharArray(rawString, length);
bool found = false;
// Since ApplicationLanguages:::Languages uses long names, we compare the "pre-dash" part of
// the language and filter it out, if it is already covered by a more specialized form.
foreach (const QString &lang, result) {
int dashIndex = lang.indexOf('-');
// There will not be any long name after the first short name was found, so we can stop.
if (dashIndex == -1)
break;
if (lang.leftRef(dashIndex) == qLanguage) {
found = true;
break;
}
}
if (!found)
result << qLanguage;
}
return result;
#endif // Q_OS_WINRT
}

View File

@ -2622,6 +2622,13 @@ QXmlStreamEntityDeclaration::~QXmlStreamEntityDeclaration()
{
}
/*! \fn QXmlStreamStringRef::swap(QXmlStreamStringRef &other)
\since 5.6
Swaps this string reference's contents with \a other.
This function is very fast and never fails.
*/
/*! \fn QStringRef QXmlStreamEntityDeclaration::name() const
Returns the entity name.

View File

@ -53,13 +53,37 @@ public:
inline QXmlStreamStringRef(const QStringRef &aString)
:m_string(aString.string()?*aString.string():QString()), m_position(aString.position()), m_size(aString.size()){}
inline QXmlStreamStringRef(const QString &aString):m_string(aString), m_position(0), m_size(aString.size()){}
inline ~QXmlStreamStringRef(){}
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
QXmlStreamStringRef(const QXmlStreamStringRef &other) // = default
: m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) {}
#ifdef Q_COMPILER_RVALUE_REFS
QXmlStreamStringRef(QXmlStreamStringRef &&other) Q_DECL_NOTHROW // = default
: m_string(std::move(other.m_string)), m_position(other.m_position), m_size(other.m_size) {}
QXmlStreamStringRef &operator=(QXmlStreamStringRef &&other) Q_DECL_NOTHROW // = default
{ swap(other); return *this; }
#endif
QXmlStreamStringRef &operator=(const QXmlStreamStringRef &other) // = default
{ m_string = other.m_string; m_position = other.m_position; m_size = other.m_size; return *this; }
inline ~QXmlStreamStringRef() {} // ### this prevents (or deprecates) all the move/copy special member functions,
// ### that's why we need to provide them by hand above. We can't remove it in
// ### Qt 5, since that would change the way its passed to functions. In Qt 6, remove all.
#endif // Qt < 6.0
void swap(QXmlStreamStringRef &other) Q_DECL_NOTHROW
{
qSwap(m_string, other.m_string);
qSwap(m_position, other.m_position);
qSwap(m_size, other.m_size);
}
inline void clear() { m_string.clear(); m_position = m_size = 0; }
inline operator QStringRef() const { return QStringRef(&m_string, m_position, m_size); }
inline const QString *string() const { return &m_string; }
inline int position() const { return m_position; }
inline int size() const { return m_size; }
};
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QXmlStreamStringRef)
class QXmlStreamReaderPrivate;

View File

@ -46,13 +46,21 @@ QT_BEGIN_NAMESPACE
PBM/PGM/PPM (ASCII and RAW) image read/write functions
*****************************************************************************/
static void discard_pbm_line(QIODevice *d)
{
const int buflen = 100;
char buf[buflen];
int res = 0;
do {
res = d->readLine(buf, buflen);
} while (res > 0 && buf[res-1] != '\n');
}
static int read_pbm_int(QIODevice *d)
{
char c;
int val = -1;
bool digit;
const int buflen = 100;
char buf[buflen];
for (;;) {
if (!d->getChar(&c)) // end of file
break;
@ -63,7 +71,7 @@ static int read_pbm_int(QIODevice *d)
continue;
} else {
if (c == '#') // comment
d->readLine(buf, buflen);
discard_pbm_line(d);
break;
}
}
@ -72,7 +80,7 @@ static int read_pbm_int(QIODevice *d)
else if (isspace((uchar) c))
continue;
else if (c == '#')
(void)d->readLine(buf, buflen);
discard_pbm_line(d);
else
break;
}

View File

@ -1853,16 +1853,23 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
if (!window)
return;
QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers, e->source);
ev.setTimestamp(e->timestamp);
#ifndef QT_NO_CURSOR
if (!e->synthetic()) {
if (const QScreen *screen = window->screen())
if (QPlatformCursor *cursor = screen->handle()->cursor())
if (QPlatformCursor *cursor = screen->handle()->cursor()) {
const QPointF nativeLocalPoint = QHighDpi::toNativePixels(localPoint, screen);
const QPointF nativeGlobalPoint = QHighDpi::toNativePixels(globalPoint, screen);
QMouseEvent ev(type, nativeLocalPoint, nativeLocalPoint, nativeGlobalPoint,
button, buttons, e->modifiers, e->source);
ev.setTimestamp(e->timestamp);
cursor->pointerEvent(ev);
}
}
#endif
QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers, e->source);
ev.setTimestamp(e->timestamp);
if (window->d_func()->blockedByModalWindow) {
// a modal window is blocking this window, don't allow mouse events through
return;

View File

@ -90,7 +90,7 @@ QWindow *QPlatformScreen::topLevelAt(const QPoint & pos) const
QWindowList list = QGuiApplication::topLevelWindows();
for (int i = list.size()-1; i >= 0; --i) {
QWindow *w = list[i];
if (w->isVisible() && w->geometry().contains(pos))
if (w->isVisible() && QHighDpi::toNativePixels(w->geometry(), w).contains(pos))
return w;
}

View File

@ -224,16 +224,16 @@ static inline QRect deviceRect(const QRect &rect, QWindow *window)
return deviceRect;
}
static QRegion deviceRegion(const QRegion &region, QWindow *window)
static QRegion deviceRegion(const QRegion &region, QWindow *window, const QPoint &offset)
{
if (!(window->devicePixelRatio() > 1))
if (offset.isNull() && window->devicePixelRatio() <= 1)
return region;
QVector<QRect> rects;
const QVector<QRect> regionRects = region.rects();
rects.reserve(regionRects.count());
foreach (const QRect &rect, regionRects)
rects.append(deviceRect(rect, window));
rects.append(deviceRect(rect.translated(offset), window));
QRegion deviceRegion;
deviceRegion.setRects(rects.constData(), rects.count());
@ -246,10 +246,12 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)
topLeftRect.width(), topLeftRect.height());
}
static void blit(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect,
QOpenGLTextureBlitter *blitter)
static void blitTextureForWidget(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect,
QOpenGLTextureBlitter *blitter, const QPoint &offset)
{
const QRect rectInWindow = textures->geometry(idx);
QRect rectInWindow = textures->geometry(idx);
// relative to the TLW, not necessarily our window (if the flush is for a native child widget), have to adjust
rectInWindow.translate(-offset);
QRect clipRect = textures->clipRect(idx);
if (clipRect.isEmpty())
clipRect = QRect(QPoint(0, 0), rectInWindow.size());
@ -274,7 +276,9 @@ static void blit(const QPlatformTextureList *textures, int idx, QWindow *window,
and composes using OpenGL. May be reimplemented in subclasses if there
is a more efficient native way to do it.
Note that the \a offset parameter is currently unused.
\note \a region is relative to the window which may not be top-level in case
\a window corresponds to a native child widget. \a offset is the position of
the native child relative to the top-level window.
*/
void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &region,
@ -282,7 +286,8 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
QPlatformTextureList *textures, QOpenGLContext *context,
bool translucentBackground)
{
Q_UNUSED(offset);
if (!qt_window_private(window)->receivedExpose)
return;
if (!context->makeCurrent(window)) {
qWarning("composeAndFlush: makeCurrent() failed");
@ -306,7 +311,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
// Textures for renderToTexture widgets.
for (int i = 0; i < textures->count(); ++i) {
if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop))
blit(textures, i, window, deviceWindowRect, d_ptr->blitter);
blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset);
}
funcs->glEnable(GL_BLEND);
@ -348,17 +353,26 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
textureId = d_ptr->textureId;
} else {
TextureFlags flags = 0;
textureId = toTexture(deviceRegion(region, window), &d_ptr->textureSize, &flags);
textureId = toTexture(deviceRegion(region, window, offset), &d_ptr->textureSize, &flags);
d_ptr->needsSwizzle = (flags & TextureSwizzle) != 0;
if (flags & TextureFlip)
origin = QOpenGLTextureBlitter::OriginBottomLeft;
}
if (textureId) {
QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(QRect(QPoint(), d_ptr->textureSize), deviceWindowRect);
if (d_ptr->needsSwizzle)
d_ptr->blitter->setSwizzleRB(true);
d_ptr->blitter->blit(textureId, target, origin);
// offset is usually (0, 0) unless we have native child widgets.
if (offset.isNull()) {
d_ptr->blitter->blit(textureId, QMatrix4x4(), origin);
} else {
// The backingstore is for the entire tlw. offset tells the position of the native child in the tlw.
const QRect srcRect = toBottomLeftRect(deviceWindowRect.translated(offset), d_ptr->textureSize.height());
const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(deviceRect(srcRect, window),
d_ptr->textureSize,
origin);
d_ptr->blitter->blit(textureId, QMatrix4x4(), source);
}
if (d_ptr->needsSwizzle)
d_ptr->blitter->setSwizzleRB(false);
}
@ -366,7 +380,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
// Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set.
for (int i = 0; i < textures->count(); ++i) {
if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop))
blit(textures, i, window, deviceWindowRect, d_ptr->blitter);
blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset);
}
funcs->glDisable(GL_BLEND);
@ -413,6 +427,8 @@ QImage QPlatformBackingStore::toImage() const
If the image has to be flipped (e.g. because the texture is attached to an FBO), \a
flags will be set to include \c TextureFlip.
\note \a dirtyRegion is relative to the backingstore so no adjustment is needed.
*/
GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const
{

View File

@ -2617,7 +2617,7 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
inside the line, taking account of the \a edge.
If \a cursorPos is not a valid cursor position, the nearest valid
cursor position will be used instead, and cpos will be modified to
cursor position will be used instead, and \a cursorPos will be modified to
point to this valid cursor position.
\sa xToCursor()

View File

@ -254,6 +254,10 @@ void QHttpNetworkConnectionChannel::handleUnexpectedEOF()
close();
reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::RemoteHostClosedError, socket);
emit reply->finishedWithError(QNetworkReply::RemoteHostClosedError, reply->d_func()->errorString);
reply = 0;
if (protocolHandler)
protocolHandler->setReply(0);
request = QHttpNetworkRequest();
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
} else {
reconnectAttempts--;

View File

@ -33,6 +33,7 @@
#include "qhostinfo_p.h"
#include <qfunctions_winrt.h>
#include <qurl.h>
#include <wrl.h>
@ -49,6 +50,8 @@ using namespace ABI::Windows::Networking::Sockets;
QT_BEGIN_NAMESPACE
#define E_NO_SUCH_HOST 0x80072af9
//#define QHOSTINFO_DEBUG
QHostInfo QHostInfoAgent::fromName(const QString &hostName)
@ -74,19 +77,22 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
ComPtr<IHostNameFactory> hostnameFactory;
HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
IID_PPV_ARGS(&hostnameFactory));
Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr)));
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IHostName> host;
HStringReference hostNameRef((const wchar_t*)hostName.utf16());
hostnameFactory->CreateHostName(hostNameRef.Get(), &host);
hr = hostnameFactory->CreateHostName(hostNameRef.Get(), &host);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IDatagramSocketStatics> datagramSocketStatics;
GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &datagramSocketStatics);
hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &datagramSocketStatics);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IAsyncOperation<IVectorView<EndpointPair *> *>> op;
datagramSocketStatics->GetEndpointPairsAsync(host.Get(),
hr = datagramSocketStatics->GetEndpointPairsAsync(host.Get(),
HString::MakeReference(L"0").Get(),
&op);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IVectorView<EndpointPair *>> endpointPairs;
hr = op->GetResults(&endpointPairs);
@ -98,26 +104,35 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
return results;
}
if (!endpointPairs)
if (hr == E_NO_SUCH_HOST || !endpointPairs) {
results.setError(QHostInfo::HostNotFound);
results.setErrorString(tr("Host %1 could not be found.").arg(hostName));
return results;
}
Q_ASSERT_SUCCEEDED(hr);
unsigned int size;
endpointPairs->get_Size(&size);
hr = endpointPairs->get_Size(&size);
Q_ASSERT_SUCCEEDED(hr);
QList<QHostAddress> addresses;
for (unsigned int i = 0; i < size; ++i) {
ComPtr<IEndpointPair> endpointpair;
endpointPairs->GetAt(i, &endpointpair);
hr = endpointPairs->GetAt(i, &endpointpair);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IHostName> remoteHost;
endpointpair->get_RemoteHostName(&remoteHost);
hr = endpointpair->get_RemoteHostName(&remoteHost);
Q_ASSERT_SUCCEEDED(hr);
if (!remoteHost)
continue;
HostNameType type;
remoteHost->get_Type(&type);
hr = remoteHost->get_Type(&type);
Q_ASSERT_SUCCEEDED(hr);
if (type == HostNameType_DomainName)
continue;
HString name;
remoteHost->get_CanonicalName(name.GetAddressOf());
hr = remoteHost->get_CanonicalName(name.GetAddressOf());
Q_ASSERT_SUCCEEDED(hr);
UINT32 length;
PCWSTR rawString = name.GetRawBuffer(&length);
QHostAddress addr;

View File

@ -89,6 +89,9 @@ static QNetworkInterfacePrivate *interfaceFromProfile(IConnectionProfile *profil
ComPtr<INetworkAdapter> adapter;
hr = profile->get_NetworkAdapter(&adapter);
// Indicates that no internet connection is available/the device is in airplane mode
if (hr == E_INVALIDARG)
return 0;
Q_ASSERT_SUCCEEDED(hr);
UINT32 type;
hr = adapter->get_IanaInterfaceType(&type);

View File

@ -23,6 +23,7 @@ contains(QT_CONFIG,egl) {
$$PWD/qxlibeglintegration_p.h
SOURCES += \
$$PWD/qxlibeglintegration.cpp
LIBS_PRIVATE += $$QMAKE_LIBS_X11
}
CONFIG += egl
}

View File

@ -84,6 +84,15 @@ typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC) (EGLDispla
typedef void *EGLStreamKHR;
typedef quint64 EGLuint64KHR;
#define EGL_NO_STREAM_KHR ((EGLStreamKHR)0)
#define EGL_STREAM_STATE_KHR 0x3214
#define EGL_STREAM_STATE_CREATED_KHR 0x3215
#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216
#define EGL_STREAM_STATE_EMPTY_KHR 0x3217
#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218
#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219
#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A
#define EGL_BAD_STREAM_KHR 0x321B
#define EGL_BAD_STATE_KHR 0x321C
typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);

View File

@ -43,6 +43,7 @@
#include <qplatformdefs.h>
#include <private/qcore_unix_p.h> // overrides QT_OPEN
#include <private/qhighdpiscaling_p.h>
#include <errno.h>
@ -141,7 +142,8 @@ bool QEvdevMouseHandler::getHardwareMaximum()
m_hardwareHeight = absInfo.maximum - absInfo.minimum;
QRect g = QGuiApplication::primaryScreen()->virtualGeometry();
QScreen *primaryScreen = QGuiApplication::primaryScreen();
QRect g = QHighDpi::toNativePixels(primaryScreen->virtualGeometry(), primaryScreen);
m_hardwareScalerX = static_cast<qreal>(m_hardwareWidth) / (g.right() - g.left());
m_hardwareScalerY = static_cast<qreal>(m_hardwareHeight) / (g.bottom() - g.top());

View File

@ -41,6 +41,7 @@
#include <QtPlatformSupport/private/qdevicediscovery_p.h>
#include <private/qguiapplication_p.h>
#include <private/qinputdevicemanager_p_p.h>
#include <private/qhighdpiscaling_p.h>
QT_BEGIN_NAMESPACE
@ -106,7 +107,8 @@ QEvdevMouseManager::~QEvdevMouseManager()
void QEvdevMouseManager::clampPosition()
{
// clamp to screen geometry
QRect g = QGuiApplication::primaryScreen()->virtualGeometry();
QScreen *primaryScreen = QGuiApplication::primaryScreen();
QRect g = QHighDpi::toNativePixels(primaryScreen->virtualGeometry(), primaryScreen);
if (m_x + m_xoffset < g.left())
m_x = g.left() - m_xoffset;
else if (m_x + m_xoffset > g.right())

View File

@ -36,6 +36,7 @@
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
#include <qpa/qwindowsysteminterface.h>
#include <private/qhighdpiscaling_p.h>
QT_BEGIN_NAMESPACE
@ -81,7 +82,8 @@ void QLibInputPointer::processMotion(libinput_event_pointer *e)
{
const double dx = libinput_event_pointer_get_dx(e);
const double dy = libinput_event_pointer_get_dy(e);
const QRect g = QGuiApplication::primaryScreen()->virtualGeometry();
QScreen * const primaryScreen = QGuiApplication::primaryScreen();
const QRect g = QHighDpi::toNativePixels(primaryScreen->virtualGeometry(), primaryScreen);
m_pos.setX(qBound(g.left(), qRound(m_pos.x() + dx), g.right()));
m_pos.setY(qBound(g.top(), qRound(m_pos.y() + dy), g.bottom()));
@ -110,7 +112,9 @@ void QLibInputPointer::processAxis(libinput_event_pointer *e)
void QLibInputPointer::setPos(const QPoint &pos)
{
const QRect g = QGuiApplication::primaryScreen()->virtualGeometry();
QScreen * const primaryScreen = QGuiApplication::primaryScreen();
const QRect g = QHighDpi::toNativePixels(primaryScreen->virtualGeometry(), primaryScreen);
m_pos.setX(qBound(g.left(), pos.x(), g.right()));
m_pos.setY(qBound(g.top(), pos.y(), g.bottom()));
}

View File

@ -201,6 +201,9 @@ static QNetworkConfiguration::BearerType qGetInterfaceType(const QString &interf
ComPtr<INetworkAdapter> adapter;
hr = profile->get_NetworkAdapter(&adapter);
// Indicates that no internet connection is available/the device is in airplane mode
if (hr == E_INVALIDARG)
return QNetworkConfiguration::BearerUnknown;
Q_ASSERT_SUCCEEDED(hr);
GUID id;
hr = adapter->get_NetworkAdapterId(&id);

View File

@ -39,12 +39,12 @@
#include "qwindowsdirect2dwindow.h"
#include "qwindowscontext.h"
#include "qwindowsguieventdispatcher.h"
#include <qplatformdefs.h>
#include <QtCore/QCoreApplication>
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/qpa/qwindowsysteminterface.h>
#include <QtPlatformSupport/private/qwindowsguieventdispatcher_p.h>
QT_BEGIN_NAMESPACE

View File

@ -219,6 +219,11 @@ QDpi QEGLDeviceIntegration::logicalDpi() const
25.4 * s.height() / ps.height());
}
qreal QEGLDeviceIntegration::pixelDensity() const
{
return logicalDpi().first / qreal(100);
}
Qt::ScreenOrientation QEGLDeviceIntegration::nativeOrientation() const
{
return Qt::PrimaryOrientation;

View File

@ -75,6 +75,7 @@ public:
virtual QSizeF physicalScreenSize() const;
virtual QSize screenSize() const;
virtual QDpi logicalDpi() const;
virtual qreal pixelDensity() const;
virtual Qt::ScreenOrientation nativeOrientation() const;
virtual Qt::ScreenOrientation orientation() const;
virtual int screenDepth() const;

View File

@ -82,6 +82,11 @@ QDpi QEglFSScreen::logicalDpi() const
return qt_egl_device_integration()->logicalDpi();
}
qreal QEglFSScreen::pixelDensity() const
{
return qt_egl_device_integration()->pixelDensity();
}
Qt::ScreenOrientation QEglFSScreen::nativeOrientation() const
{
return qt_egl_device_integration()->nativeOrientation();

View File

@ -55,6 +55,7 @@ public:
QSizeF physicalSize() const Q_DECL_OVERRIDE;
QDpi logicalDpi() const Q_DECL_OVERRIDE;
qreal pixelDensity() const Q_DECL_OVERRIDE;
Qt::ScreenOrientation nativeOrientation() const Q_DECL_OVERRIDE;
Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE;

View File

@ -73,7 +73,7 @@ private:
QRect m_geometry;
QRect m_availableGeometry;
int m_depth;
uint m_unscaledDpi;
uint m_pixelDensity;
QSizeF m_physicalSize;
QIOSOrientationListener *m_orientationListener;
};

View File

@ -170,23 +170,28 @@ QIOSScreen::QIOSScreen(UIScreen *screen)
if (screen == [UIScreen mainScreen]) {
QString deviceIdentifier = deviceModelIdentifier();
if (deviceIdentifier == QLatin1String("iPhone2,1") /* iPhone 3GS */
|| deviceIdentifier == QLatin1String("iPod3,1") /* iPod touch 3G */) {
m_depth = 18;
} else {
m_depth = 24;
}
// Based on https://en.wikipedia.org/wiki/List_of_iOS_devices#Display
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad
&& !deviceIdentifier.contains(QRegularExpression("^iPad2,[567]$")) /* excluding iPad Mini */) {
m_unscaledDpi = 132;
// iPhone (1st gen), 3G, 3GS, and iPod Touch (1st3rd gen) are 18-bit devices
if (deviceIdentifier.contains(QRegularExpression("^(iPhone1,[12]|iPhone2,1|iPod[1-3],1)$")))
m_depth = 18;
else
m_depth = 24;
if (deviceIdentifier.contains(QRegularExpression("^iPhone(7,1|8,2)$"))) {
// iPhone 6 Plus or iPhone 6S Plus
m_pixelDensity = 401;
} else if (deviceIdentifier.contains(QRegularExpression("^iPad(1,1|2,[1-4]|3,[1-6]|4,[1-3]|5,[3-4]|6,[7-8])$"))) {
// All iPads except the iPad Mini series
m_pixelDensity = 132 * devicePixelRatio();
} else {
m_unscaledDpi = 163; // Regular iPhone DPI
// All non-Plus iPhones, and iPad Minis
m_pixelDensity = 163 * devicePixelRatio();
}
} else {
// External display, hard to say
m_depth = 24;
m_unscaledDpi = 96;
m_pixelDensity = 96;
}
for (UIWindow *existingWindow in [[UIApplication sharedApplication] windows]) {
@ -249,7 +254,7 @@ void QIOSScreen::updateProperties()
if (m_geometry != previousGeometry) {
const qreal millimetersPerInch = 25.4;
m_physicalSize = QSizeF(m_geometry.size()) / m_unscaledDpi * millimetersPerInch;
m_physicalSize = QSizeF(m_geometry.size() * devicePixelRatio()) / m_pixelDensity * millimetersPerInch;
}
// At construction time, we don't yet have an associated QScreen, but we still want

View File

@ -57,9 +57,9 @@
},
{
"id": 5,
"description": "Intel GMA 3150 crashes (QTBUG-43243)",
"description": "Intel GMA 3150 (QTBUG-43243), Mobile Intel 945GM (QTBUG-47435) crash",
"vendor_id": "0x8086",
"device_id": [ "0xA001", "0xA011" ],
"device_id": [ "0xA001", "0xA011", "0x27A0" ],
"os": {
"type": "win"
},

View File

@ -84,7 +84,8 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion &region,
if ((flags & Qt::FramelessWindowHint) && QWindowsWindow::setWindowLayered(rw->handle(), flags, hasAlpha, rw->opacity()) && hasAlpha) {
// Windows with alpha: Use blend function to update.
QRect r = QHighDpi::toNativePixels(window->frameGeometry(), window);
QPoint frameOffset(QHighDpi::toNativePixels(QPoint(window->frameMargins().left(), window->frameMargins().top()), window));
QPoint frameOffset(QHighDpi::toNativePixels(QPoint(window->frameMargins().left(), window->frameMargins().top()),
static_cast<const QWindow *>(Q_NULLPTR)));
QRect dirtyRect = br.translated(offset + frameOffset);
SIZE size = {r.width(), r.height()};

View File

@ -67,20 +67,15 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap);
\ingroup qt-lighthouse-win
*/
QWindowsCursorCacheKey::QWindowsCursorCacheKey(const QCursor &c)
: shape(c.shape()), bitmapCacheKey(0), maskCacheKey(0)
QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c)
: bitmapCacheKey(c.pixmap().cacheKey()), maskCacheKey(0)
{
if (shape == Qt::BitmapCursor) {
const qint64 pixmapCacheKey = c.pixmap().cacheKey();
if (pixmapCacheKey) {
bitmapCacheKey = pixmapCacheKey;
} else {
if (!bitmapCacheKey) {
Q_ASSERT(c.bitmap());
Q_ASSERT(c.mask());
bitmapCacheKey = c.bitmap()->cacheKey();
maskCacheKey = c.mask()->cacheKey();
}
}
}
/*!
@ -206,6 +201,17 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits,
#endif
}
// Create a cursor from image and mask of the format QImage::Format_Mono.
static HCURSOR createBitmapCursor(const QCursor &cursor)
{
Q_ASSERT(cursor.shape() == Qt::BitmapCursor && cursor.bitmap());
const QImage bbits = cursor.bitmap()->toImage().convertToFormat(QImage::Format_Mono);
const QImage mbits = cursor.mask()->toImage().convertToFormat(QImage::Format_Mono);
const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1));
const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
return createBitmapCursor(bbits, mbits, cursor.hotSpot(), invb, invm);
}
static inline QSize systemCursorSize() { return QSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); }
static inline QSize standardCursorSize() { return QSize(32, 32); }
@ -215,7 +221,7 @@ static inline QSize standardCursorSize() { return QSize(32, 32); }
// createBitmapCursor() only work for standard sizes (32,48,64...), which does
// not work when scaling the 16x16 openhand cursor bitmaps to 150% (resulting
// in a non-standard 24x24 size).
static QCursor createPixmapCursorFromData(const QSize &systemCursorSize,
static QWindowsCursor::PixmapCursor createPixmapCursorFromData(const QSize &systemCursorSize,
// The cursor size the bitmap is targeted for
const QSize &bitmapTargetCursorSize,
// The actual size of the bitmap data
@ -233,10 +239,10 @@ static QCursor createPixmapCursorFromData(const QSize &systemCursorSize,
rawImage = rawImage.transformed(transform, Qt::SmoothTransformation);
}
const QPoint hotSpot(rawImage.width() / 2, rawImage.height() / 2);
return QCursor(rawImage, hotSpot.x(), hotSpot.y());
return QWindowsCursor::PixmapCursor(rawImage, hotSpot);
}
QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
{
// Non-standard Windows cursors are created from bitmaps
static const uchar vsplit_bits[] = {
@ -412,14 +418,14 @@ QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
case Qt::ClosedHandCursor:
return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, closedhand_bits, closedhandm_bits);
case Qt::DragCopyCursor:
return QCursor(QPixmap(copyDragCursorXpmC), 0, 0);
return QWindowsCursor::PixmapCursor(QPixmap(copyDragCursorXpmC), QPoint(0, 0));
case Qt::DragMoveCursor:
return QCursor(QPixmap(moveDragCursorXpmC), 0, 0);
return QWindowsCursor::PixmapCursor(QPixmap(moveDragCursorXpmC), QPoint(0, 0));
case Qt::DragLinkCursor:
return QCursor(QPixmap(linkDragCursorXpmC), 0, 0);
return QWindowsCursor::PixmapCursor(QPixmap(linkDragCursorXpmC), QPoint(0, 0));
}
return QCursor();
return QWindowsCursor::PixmapCursor();
}
#else // Q_OS_WINCE || QT_NO_IMAGEFORMAT_PNG
struct QWindowsCustomPngCursor {
@ -430,7 +436,7 @@ struct QWindowsCustomPngCursor {
int hotSpotY;
};
QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
{
static const QWindowsCustomPngCursor pngCursors[] = {
{ Qt::SplitVCursor, 32, "splitvcursor_32.png", 11, 11 },
@ -473,11 +479,11 @@ QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
}
if (!bestFit)
return QCursor();
return PixmapCursor();
const QPixmap rawImage(QStringLiteral(":/qt-project.org/windows/cursors/images/") +
QString::fromLatin1(bestFit->fileName));
return QCursor(rawImage, bestFit->hotSpotX, bestFit->hotSpotY);
return PixmapCursor(rawImage, QPoint(bestFit->hotSpotX, bestFit->hotSpotY));
}
#endif // Q_OS_WINCE || QT_NO_IMAGEFORMAT_PNG
@ -486,8 +492,10 @@ struct QWindowsStandardCursorMapping {
LPCWSTR resource;
};
HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape)
{
Q_ASSERT(cursorShape != Qt::BitmapCursor);
static const QWindowsStandardCursorMapping standardCursors[] = {
{ Qt::ArrowCursor, IDC_ARROW},
{ Qt::UpArrowCursor, IDC_UPARROW },
@ -505,18 +513,7 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
{ Qt::PointingHandCursor, IDC_HAND }
};
const Qt::CursorShape cursorShape = c.shape();
switch (cursorShape) {
case Qt::BitmapCursor: {
const QPixmap pixmap = c.pixmap();
if (!pixmap.isNull())
return QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot());
const QImage bbits = c.bitmap()->toImage().convertToFormat(QImage::Format_Mono);
const QImage mbits = c.mask()->toImage().convertToFormat(QImage::Format_Mono);
const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1));
const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
return createBitmapCursor(bbits, mbits, c.hotSpot(), invb, invm);
}
case Qt::BlankCursor: {
QImage blank = QImage(systemCursorSize(), QImage::Format_Mono);
blank.fill(0); // ignore color table
@ -529,7 +526,7 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
case Qt::DragCopyCursor:
case Qt::DragMoveCursor:
case Qt::DragLinkCursor:
return createSystemCursor(customCursor(cursorShape));
return QWindowsCursor::createPixmapCursor(customCursor(cursorShape));
default:
break;
}
@ -554,37 +551,41 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
\brief Return cached standard cursor resources or create new ones.
*/
QWindowsWindowCursor QWindowsCursor::standardWindowCursor(Qt::CursorShape shape)
CursorHandlePtr QWindowsCursor::standardWindowCursor(Qt::CursorShape shape)
{
const QWindowsCursorCacheKey key(shape);
CursorCache::iterator it = m_cursorCache.find(key);
if (it == m_cursorCache.end())
it = m_cursorCache.insert(key, QWindowsWindowCursor(QCursor(shape)));
return it.value();
StandardCursorCache::Iterator it = m_standardCursorCache.find(shape);
if (it == m_standardCursorCache.end()) {
if (const HCURSOR hc = QWindowsCursor::createCursorFromShape(shape))
it = m_standardCursorCache.insert(shape, CursorHandlePtr(new CursorHandle(hc)));
}
return it != m_standardCursorCache.end() ? it.value() : CursorHandlePtr(new CursorHandle);
}
/*!
\brief Return cached pixmap cursor or create new one.
*/
QWindowsWindowCursor QWindowsCursor::pixmapWindowCursor(const QCursor &c)
CursorHandlePtr QWindowsCursor::pixmapWindowCursor(const QCursor &c)
{
const QWindowsCursorCacheKey cacheKey(c);
CursorCache::iterator it = m_cursorCache.find(cacheKey);
if (it == m_cursorCache.end()) {
if (m_cursorCache.size() > 50) {
const QWindowsPixmapCursorCacheKey cacheKey(c);
PixmapCursorCache::iterator it = m_pixmapCursorCache.find(cacheKey);
if (it == m_pixmapCursorCache.end()) {
if (m_pixmapCursorCache.size() > 50) {
// Prevent the cursor cache from growing indefinitely hitting GDI resource
// limits if new pixmap cursors are created repetitively by purging out
// all-noncurrent pixmap cursors (QTBUG-43515)
const HCURSOR currentCursor = GetCursor();
for (it = m_cursorCache.begin(); it != m_cursorCache.end() ; ) {
if (it.key().bitmapCacheKey && it.value().handle() != currentCursor)
it = m_cursorCache.erase(it);
for (it = m_pixmapCursorCache.begin(); it != m_pixmapCursorCache.end() ; ) {
if (it.value()->handle() != currentCursor)
it = m_pixmapCursorCache.erase(it);
else
++it;
}
}
it = m_cursorCache.insert(cacheKey, QWindowsWindowCursor(c));
const QPixmap pixmap = c.pixmap();
const HCURSOR hc = pixmap.isNull()
? createBitmapCursor(c) : QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot());
it = m_pixmapCursorCache.insert(cacheKey, CursorHandlePtr(new CursorHandle(hc)));
}
return it.value();
}
@ -606,13 +607,13 @@ void QWindowsCursor::changeCursor(QCursor *cursorIn, QWindow *window)
if (!window)
return;
if (!cursorIn) {
QWindowsWindow::baseWindowOf(window)->setCursor(QWindowsWindowCursor());
QWindowsWindow::baseWindowOf(window)->setCursor(CursorHandlePtr(new CursorHandle));
return;
}
const QWindowsWindowCursor wcursor =
const CursorHandlePtr wcursor =
cursorIn->shape() == Qt::BitmapCursor ?
pixmapWindowCursor(*cursorIn) : standardWindowCursor(cursorIn->shape());
if (wcursor.handle()) {
if (wcursor->handle()) {
QWindowsWindow::baseWindowOf(window)->setCursor(wcursor);
} else {
qWarning("%s: Unable to obtain system cursor for %d",
@ -658,78 +659,11 @@ void QWindowsCursor::setPos(const QPoint &pos)
\brief Per-Window cursor. Contains a QCursor and manages its associated system
cursor handle resource.
Based on QSharedDataPointer, so that it can be passed around and
used as a property of QWindowsBaseWindow.
\internal
\ingroup qt-lighthouse-win
\sa QWindowsCursor
*/
class QWindowsWindowCursorData : public QSharedData
{
public:
QWindowsWindowCursorData() : m_cursor(Qt::ArrowCursor), m_handle(0) {}
explicit QWindowsWindowCursorData(const QCursor &c);
~QWindowsWindowCursorData();
const QCursor m_cursor;
const HCURSOR m_handle;
};
QWindowsWindowCursorData::QWindowsWindowCursorData(const QCursor &c) :
m_cursor(c),
m_handle(QWindowsCursor::createSystemCursor(c))
{
}
QWindowsWindowCursorData::~QWindowsWindowCursorData()
{
if (m_handle)
DestroyCursor(m_handle);
}
QWindowsWindowCursor::QWindowsWindowCursor() :
m_data(new QWindowsWindowCursorData)
{
}
QWindowsWindowCursor::QWindowsWindowCursor(const QCursor &c) :
m_data(new QWindowsWindowCursorData(c))
{
}
QWindowsWindowCursor::~QWindowsWindowCursor()
{
}
QWindowsWindowCursor::QWindowsWindowCursor(const QWindowsWindowCursor &rhs) :
m_data(rhs.m_data)
{
}
QWindowsWindowCursor & QWindowsWindowCursor::operator =(const QWindowsWindowCursor &rhs)
{
if (this != &rhs)
m_data.operator =(rhs.m_data);
return *this;
}
bool QWindowsWindowCursor::isNull() const
{
return m_data->m_handle == 0;
}
QCursor QWindowsWindowCursor::cursor() const
{
return m_data->m_cursor;
}
HCURSOR QWindowsWindowCursor::handle() const
{
return m_data->m_handle;
}
QT_END_NAMESPACE
#endif // !QT_NO_CURSOR

View File

@ -37,51 +37,49 @@
#include "qtwindows_additional.h"
#include <qpa/qplatformcursor.h>
#include <QtCore/QSharedDataPointer>
#include <QtCore/QSharedPointer>
#include <QtCore/QHash>
QT_BEGIN_NAMESPACE
class QWindowsWindowCursorData;
struct QWindowsCursorCacheKey
struct QWindowsPixmapCursorCacheKey
{
explicit QWindowsCursorCacheKey(const QCursor &c);
explicit QWindowsCursorCacheKey(Qt::CursorShape s) : shape(s), bitmapCacheKey(0), maskCacheKey(0) {}
QWindowsCursorCacheKey() : shape(Qt::CustomCursor), bitmapCacheKey(0), maskCacheKey(0) {}
explicit QWindowsPixmapCursorCacheKey(const QCursor &c);
Qt::CursorShape shape;
qint64 bitmapCacheKey;
qint64 maskCacheKey;
};
inline bool operator==(const QWindowsCursorCacheKey &k1, const QWindowsCursorCacheKey &k2)
inline bool operator==(const QWindowsPixmapCursorCacheKey &k1, const QWindowsPixmapCursorCacheKey &k2)
{
return k1.shape == k2.shape && k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey;
return k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey;
}
inline uint qHash(const QWindowsCursorCacheKey &k, uint seed) Q_DECL_NOTHROW
inline uint qHash(const QWindowsPixmapCursorCacheKey &k, uint seed) Q_DECL_NOTHROW
{
return (uint(k.shape) + uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed;
return (uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed;
}
class QWindowsWindowCursor
class CursorHandle
{
Q_DISABLE_COPY(CursorHandle)
public:
QWindowsWindowCursor();
explicit QWindowsWindowCursor(const QCursor &c);
~QWindowsWindowCursor();
QWindowsWindowCursor(const QWindowsWindowCursor &c);
QWindowsWindowCursor &operator=(const QWindowsWindowCursor &c);
explicit CursorHandle(HCURSOR hcursor = Q_NULLPTR) : m_hcursor(hcursor) {}
~CursorHandle()
{
if (m_hcursor)
DestroyCursor(m_hcursor);
}
bool isNull() const;
QCursor cursor() const;
HCURSOR handle() const;
bool isNull() const { return !m_hcursor; }
HCURSOR handle() const { return m_hcursor; }
private:
QSharedDataPointer<QWindowsWindowCursorData> m_data;
const HCURSOR m_hcursor;
};
typedef QSharedPointer<CursorHandle> CursorHandlePtr;
class QWindowsCursor : public QPlatformCursor
{
public:
@ -91,6 +89,13 @@ public:
CursorSuppressed // Cursor suppressed by touch interaction (Windows 8).
};
struct PixmapCursor {
explicit PixmapCursor(const QPixmap &pix = QPixmap(), const QPoint &h = QPoint()) : pixmap(pix), hotSpot(h) {}
QPixmap pixmap;
QPoint hotSpot;
};
QWindowsCursor();
void changeCursor(QCursor * widgetCursor, QWindow * widget) Q_DECL_OVERRIDE;
@ -98,18 +103,22 @@ public:
void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
static HCURSOR createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot);
static HCURSOR createSystemCursor(const QCursor &c);
static QCursor customCursor(Qt::CursorShape cursorShape);
static HCURSOR createPixmapCursor(const PixmapCursor &pc) { return createPixmapCursor(pc.pixmap, pc.hotSpot); }
static PixmapCursor customCursor(Qt::CursorShape cursorShape);
static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape);
static QPoint mousePosition();
static CursorState cursorState();
QWindowsWindowCursor standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor);
QWindowsWindowCursor pixmapWindowCursor(const QCursor &c);
CursorHandlePtr standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor);
CursorHandlePtr pixmapWindowCursor(const QCursor &c);
private:
typedef QHash<QWindowsCursorCacheKey, QWindowsWindowCursor> CursorCache;
typedef QHash<Qt::CursorShape, CursorHandlePtr> StandardCursorCache;
typedef QHash<QWindowsPixmapCursorCacheKey, CursorHandlePtr> PixmapCursorCache;
CursorCache m_cursorCache;
StandardCursorCache m_standardCursorCache;
PixmapCursorCache m_pixmapCursorCache;
};
QT_END_NAMESPACE

View File

@ -218,23 +218,14 @@ public:
STDMETHOD(GiveFeedback)(DWORD dwEffect);
private:
class DragCursorHandle {
Q_DISABLE_COPY(DragCursorHandle)
public:
DragCursorHandle(HCURSOR c) : cursor(c) {}
~DragCursorHandle() { DestroyCursor(cursor); }
const HCURSOR cursor;
};
typedef QSharedPointer<DragCursorHandle> DragCursorHandlePtr;
struct CursorEntry {
CursorEntry() : cacheKey(0) {}
CursorEntry(const QPixmap &p, qint64 cK, const DragCursorHandlePtr &c, const QPoint &h) :
CursorEntry(const QPixmap &p, qint64 cK, const CursorHandlePtr &c, const QPoint &h) :
pixmap(p), cacheKey(cK), cursor(c), hotSpot(h) {}
QPixmap pixmap;
qint64 cacheKey; // Cache key of cursor
DragCursorHandlePtr cursor;
CursorHandlePtr cursor;
QPoint hotSpot;
};
@ -273,7 +264,7 @@ QWindowsOleDropSource::~QWindowsOleDropSource()
QDebug operator<<(QDebug d, const QWindowsOleDropSource::CursorEntry &e)
{
d << "CursorEntry:" << e.pixmap.size() << '#' << e.cacheKey
<< "HCURSOR" << e.cursor->cursor << "hotspot:" << e.hotSpot;
<< "HCURSOR" << e.cursor->handle() << "hotspot:" << e.hotSpot;
return d;
}
#endif // !QT_NO_DEBUG_STREAM
@ -343,7 +334,7 @@ void QWindowsOleDropSource::createCursors()
}
if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newPixmap, newHotSpot)) {
const CursorEntry entry(newPixmap, cacheKey, DragCursorHandlePtr(new DragCursorHandle(sysCursor)), newHotSpot);
const CursorEntry entry(newPixmap, cacheKey, CursorHandlePtr(new CursorHandle(sysCursor)), newHotSpot);
if (it == m_cursors.end())
m_cursors.insert(action, entry);
else
@ -456,7 +447,7 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect)
const CursorEntry &e = it.value();
switch (m_mode) {
case MouseDrag:
SetCursor(e.cursor->cursor);
SetCursor(e.cursor->handle());
break;
case TouchDrag:
if (!m_touchDragWindow)
@ -718,16 +709,16 @@ QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const
switch (action) {
case Qt::CopyAction:
if (m_copyDragCursor.isNull())
m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor).pixmap();
m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor).pixmap;
return m_copyDragCursor;
case Qt::TargetMoveAction:
case Qt::MoveAction:
if (m_moveDragCursor.isNull())
m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor).pixmap();
m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor).pixmap;
return m_moveDragCursor;
case Qt::LinkAction:
if (m_linkDragCursor.isNull())
m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor).pixmap();
m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor).pixmap;
return m_linkDragCursor;
default:
break;

View File

@ -393,6 +393,8 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const
return QVariant(booleanSystemParametersInfo(SPI_GETSNAPTODEFBUTTON, false));
case ContextMenuOnMouseRelease:
return QVariant(true);
case WheelScrollLines:
return dWordSystemParametersInfo(SPI_GETWHEELSCROLLLINES, 3);
default:
break;
}

View File

@ -928,6 +928,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
m_hdc(0),
m_windowState(Qt::WindowNoState),
m_opacity(1.0),
m_cursor(new CursorHandle),
m_dropTarget(0),
m_savedStyle(0),
m_format(aWindow->requestedFormat()),
@ -2113,13 +2114,13 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re
#ifndef QT_NO_CURSOR
// Return the default cursor (Arrow) from QWindowsCursor's cache.
static inline QWindowsWindowCursor defaultCursor(const QWindow *w)
static inline CursorHandlePtr defaultCursor(const QWindow *w)
{
if (QScreen *screen = w->screen())
if (const QPlatformScreen *platformScreen = screen->handle())
if (QPlatformCursor *cursor = platformScreen->cursor())
return static_cast<QWindowsCursor *>(cursor)->standardWindowCursor(Qt::ArrowCursor);
return QWindowsWindowCursor(Qt::ArrowCursor);
return CursorHandlePtr(new CursorHandle(QWindowsCursor::createCursorFromShape(Qt::ArrowCursor)));
}
// Check whether to apply a new cursor. Either the window in question is
@ -2133,7 +2134,7 @@ static inline bool applyNewCursor(const QWindow *w)
for (const QWindow *p = underMouse; p ; p = p->parent()) {
if (p == w)
return true;
if (!QWindowsWindow::baseWindowOf(p)->cursor().isNull())
if (!QWindowsWindow::baseWindowOf(p)->cursor()->isNull())
return false;
}
return false;
@ -2149,25 +2150,25 @@ static inline bool applyNewCursor(const QWindow *w)
void QWindowsWindow::applyCursor()
{
#ifndef QT_NO_CURSOR
if (m_cursor.isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel.
if (m_cursor->isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel.
if (const QWindow *p = window()->parent()) {
QWindowsWindow::baseWindowOf(p)->applyCursor();
} else {
SetCursor(defaultCursor(window()).handle());
SetCursor(defaultCursor(window())->handle());
}
} else {
SetCursor(m_cursor.handle());
SetCursor(m_cursor->handle());
}
#endif
}
void QWindowsWindow::setCursor(const QWindowsWindowCursor &c)
void QWindowsWindow::setCursor(const CursorHandlePtr &c)
{
#ifndef QT_NO_CURSOR
if (c.handle() != m_cursor.handle()) {
if (c->handle() != m_cursor->handle()) {
const bool apply = applyNewCursor(window());
qCDebug(lcQpaWindows) << window() << __FUNCTION__
<< c.cursor().shape() << " doApply=" << apply;
<< c->handle() << " doApply=" << apply;
m_cursor = c;
if (apply)
applyCursor();

View File

@ -225,9 +225,9 @@ public:
#endif // !Q_OS_WINCE
#ifndef QT_NO_CURSOR
QWindowsWindowCursor cursor() const { return m_cursor; }
CursorHandlePtr cursor() const { return m_cursor; }
#endif
void setCursor(const QWindowsWindowCursor &c);
void setCursor(const CursorHandlePtr &c);
void applyCursor();
inline bool testFlag(unsigned f) const { return (m_flags & f) != 0; }
@ -278,7 +278,7 @@ private:
Qt::WindowState m_windowState;
qreal m_opacity;
#ifndef QT_NO_CURSOR
QWindowsWindowCursor m_cursor;
CursorHandlePtr m_cursor;
#endif
QWindowsOleDropTarget *m_dropTarget;
unsigned m_savedStyle;

View File

@ -260,8 +260,10 @@ HRESULT QWinRTIntegration::onBackButtonPressed(IInspectable *, IBackPressedEvent
Q_D(QWinRTIntegration);
QWindow *window = d->mainScreen->topWindow();
QWindowSystemInterface::setSynchronousWindowSystemEvents(true);
const bool pressed = QWindowSystemInterface::handleKeyEvent(window, QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier);
const bool released = QWindowSystemInterface::handleKeyEvent(window, QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier);
const bool pressed = QWindowSystemInterface::handleExtendedKeyEvent(window, QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier,
0, 0, 0, QString(), false, 1, false);
const bool released = QWindowSystemInterface::handleExtendedKeyEvent(window, QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier,
0, 0, 0, QString(), false, 1, false);
QWindowSystemInterface::setSynchronousWindowSystemEvents(false);
args->put_Handled(pressed || released);
return S_OK;

View File

@ -500,10 +500,7 @@ void QXcbWindow::create()
properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS);
properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING);
if (platformScreen->syncRequestSupported())
m_usingSyncProtocol = supportsSyncProtocol();
else
m_usingSyncProtocol = false;
m_usingSyncProtocol = platformScreen->syncRequestSupported();
if (m_usingSyncProtocol)
properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST);

View File

@ -176,7 +176,6 @@ public Q_SLOTS:
protected:
virtual void resolveFormat() { m_format = window()->requestedFormat(); }
virtual void *createVisual() { return Q_NULLPTR; }
virtual bool supportsSyncProtocol() { return !window()->supportsOpenGL(); }
QXcbScreen *parentScreen();

View File

@ -471,6 +471,7 @@ void QSqlQueryModel::setQuery(const QString &query, const QSqlDatabase &db)
void QSqlQueryModel::clear()
{
Q_D(QSqlQueryModel);
beginResetModel();
d->error = QSqlError();
d->atEnd = true;
d->query.clear();
@ -478,6 +479,7 @@ void QSqlQueryModel::clear()
d->colOffsets.clear();
d->bottom = QModelIndex();
d->headers.clear();
endResetModel();
}
/*!

View File

@ -652,9 +652,11 @@ void QSqlRelationalTableModel::revertRow(int row)
void QSqlRelationalTableModel::clear()
{
Q_D(QSqlRelationalTableModel);
beginResetModel();
d->clearChanges();
d->relations.clear();
QSqlTableModel::clear();
endResetModel();
}

View File

@ -1262,8 +1262,10 @@ void QSqlTableModel::setFilter(const QString &filter)
void QSqlTableModel::clear()
{
Q_D(QSqlTableModel);
beginResetModel();
d->clear();
QSqlQueryModel::clear();
endResetModel();
}
/*! \reimp

View File

@ -645,12 +645,6 @@ void QOpenGLWidgetPaintDevice::ensureActiveTarget()
GLuint QOpenGLWidgetPrivate::textureId() const
{
Q_Q(const QOpenGLWidget);
if (!q->isWindow() && q->internalWinId()) {
qWarning("QOpenGLWidget cannot be used as a native child widget. Consider setting "
"Qt::WA_DontCreateNativeAncestors and Qt::AA_DontCreateNativeWidgetSiblings");
return 0;
}
return resolvedFbo ? resolvedFbo->texture() : (fbo ? fbo->texture() : 0);
}

View File

@ -60,6 +60,7 @@
# include <private/qmainwindowlayout_p.h>
#endif
#include <qpa/qplatformwindow.h>
#include <qpa/qplatformbackingstore.h>
#include "private/qwidgetwindow_p.h"
#include "qpainter.h"
#include "qtooltip.h"
@ -1834,6 +1835,8 @@ void QWidgetPrivate::deleteTLSysExtra()
delete extra->topextra->backingStore;
extra->topextra->backingStore = 0;
#ifndef QT_NO_OPENGL
qDeleteAll(extra->topextra->widgetTextures);
extra->topextra->widgetTextures.clear();
if (textureChildSeen && extra->topextra->shareContext)
extra->topextra->shareContext->doneCurrent();
delete extra->topextra->shareContext;

View File

@ -75,6 +75,7 @@ class QWidgetBackingStore;
class QGraphicsProxyWidget;
class QWidgetItemV2;
class QOpenGLContext;
class QPlatformTextureList;
class QStyle;
@ -153,6 +154,8 @@ struct QTLWExtra {
QWidgetBackingStoreTracker backingStoreTracker;
QBackingStore *backingStore;
QPainter *sharedPainter;
QWidgetWindow *window;
QOpenGLContext *shareContext;
// Implicit pointers (shared_null).
QString caption; // widget caption
@ -167,6 +170,9 @@ struct QTLWExtra {
QRect frameStrut;
QRect normalGeometry; // used by showMin/maximized/FullScreen
Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen
int initialScreenIndex; // Screen number when passing a QDesktop[Screen]Widget as parent.
QVector<QPlatformTextureList *> widgetTextures;
// *************************** Cross-platform bit fields ****************************
uint opacity : 8;
@ -210,9 +216,6 @@ struct QTLWExtra {
// starting position as 0,0 instead of the normal starting position.
bool wasMaximized;
#endif
QWidgetWindow *window;
QOpenGLContext *shareContext;
int initialScreenIndex; // Screen number when passing a QDesktop[Screen]Widget as parent.
};
struct QWExtra {

View File

@ -79,7 +79,6 @@ void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion &region, QBack
Q_ASSERT(widget);
Q_ASSERT(backingStore);
Q_ASSERT(tlw);
#if !defined(QT_NO_PAINT_DEBUG)
static int flushUpdate = qEnvironmentVariableIntValue("QT_FLUSH_UPDATE");
if (flushUpdate > 0)
@ -105,13 +104,17 @@ void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion &region, QBack
#ifndef QT_NO_OPENGL
if (widgetTextures) {
Q_ASSERT(!widgetTextures->isEmpty());
qt_window_private(tlw->windowHandle())->compositing = true;
widget->window()->d_func()->sendComposeStatus(widget->window(), false);
// A window may have alpha even when the app did not request
// WA_TranslucentBackground. Therefore the compositor needs to know whether the app intends
// to rely on translucency, in order to decide if it should clear to transparent or opaque.
const bool translucentBackground = widget->testAttribute(Qt::WA_TranslucentBackground);
// Use the tlw's context, not widget's. The difference is important with native child
// widgets where tlw != widget.
backingStore->handle()->composeAndFlush(widget->windowHandle(), region, offset, widgetTextures,
widget->d_func()->shareContext(), translucentBackground);
tlw->d_func()->shareContext(), translucentBackground);
widget->window()->d_func()->sendComposeStatus(widget->window(), true);
} else
#endif
@ -741,7 +744,6 @@ void QWidgetBackingStore::updateLists(QWidget *cur)
QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
: tlw(topLevel),
dirtyOnScreenWidgets(0),
widgetTextures(0),
fullUpdatePending(0),
updateRequestSent(0),
textureListWatcher(0),
@ -761,9 +763,6 @@ QWidgetBackingStore::~QWidgetBackingStore()
for (int c = 0; c < dirtyRenderToTextureWidgets.size(); ++c)
resetWidget(dirtyRenderToTextureWidgets.at(c));
#ifndef QT_NO_OPENGL
delete widgetTextures;
#endif
delete dirtyOnScreenWidgets;
}
@ -792,8 +791,9 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
destRect = destRect.translated(dx, dy).intersected(clipR);
const QRect sourceRect(destRect.translated(-dx, -dy));
const QRect parentRect(rect & clipR);
const bool nativeWithTextureChild = textureChildSeen && q->internalWinId();
bool accelerateMove = accelEnv && isOpaque
bool accelerateMove = accelEnv && isOpaque && !nativeWithTextureChild
#ifndef QT_NO_GRAPHICSVIEW
// No accelerate move for proxy widgets.
&& !tlw->d_func()->extra->proxyWidget
@ -913,6 +913,95 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
}
}
#ifndef QT_NO_OPENGL
static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatformTextureList *widgetTextures, QVector<QWidget *> *nativeChildren)
{
QWidgetPrivate *wd = QWidgetPrivate::get(widget);
if (wd->renderToTexture) {
QPlatformTextureList::Flags flags = 0;
if (widget->testAttribute(Qt::WA_AlwaysStackOnTop))
flags |= QPlatformTextureList::StacksOnTop;
const QRect rect(widget->mapTo(tlw, QPoint()), widget->size());
widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags);
}
for (int i = 0; i < wd->children.size(); ++i) {
QWidget *w = qobject_cast<QWidget *>(wd->children.at(i));
// Stop at native widgets but store them. Stop at hidden widgets too.
if (w && !w->isWindow() && w->internalWinId())
nativeChildren->append(w);
if (w && !w->isWindow() && !w->internalWinId() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
findTextureWidgetsRecursively(tlw, w, widgetTextures, nativeChildren);
}
}
static void findAllTextureWidgetsRecursively(QWidget *tlw, QWidget *widget)
{
// textureChildSeen does not take native child widgets into account and that's good.
if (QWidgetPrivate::get(widget)->textureChildSeen) {
QVector<QWidget *> nativeChildren;
QScopedPointer<QPlatformTextureList> tl(new QPlatformTextureList);
// Look for texture widgets (incl. widget itself) from 'widget' down,
// but skip subtrees with a parent of a native child widget.
findTextureWidgetsRecursively(tlw, widget, tl.data(), &nativeChildren);
// tl may be empty regardless of textureChildSeen if we have native or hidden children.
if (!tl->isEmpty())
QWidgetPrivate::get(tlw)->topData()->widgetTextures.append(tl.take());
// Native child widgets, if there was any, get their own separate QPlatformTextureList.
foreach (QWidget *ncw, nativeChildren) {
if (QWidgetPrivate::get(ncw)->textureChildSeen)
findAllTextureWidgetsRecursively(tlw, ncw);
}
}
}
static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget)
{
foreach (QPlatformTextureList *tl, QWidgetPrivate::get(tlw)->topData()->widgetTextures) {
Q_ASSERT(!tl->isEmpty());
for (int i = 0; i < tl->count(); ++i) {
QWidget *w = static_cast<QWidget *>(tl->source(i));
if ((w->internalWinId() && w == widget) || (!w->internalWinId() && w->nativeParentWidget() == widget))
return tl;
}
}
return 0;
}
// Watches one or more QPlatformTextureLists for changes in the lock state and
// triggers a backingstore sync when all the registered lists turn into
// unlocked state. This is essential when a custom composeAndFlush()
// implementation in a platform plugin is not synchronous and keeps
// holding on to the textures for some time even after returning from there.
QPlatformTextureListWatcher::QPlatformTextureListWatcher(QWidgetBackingStore *backingStore)
: m_backingStore(backingStore)
{
}
void QPlatformTextureListWatcher::watch(QPlatformTextureList *textureList)
{
connect(textureList, SIGNAL(locked(bool)), SLOT(onLockStatusChanged(bool)));
m_locked[textureList] = textureList->isLocked();
}
bool QPlatformTextureListWatcher::isLocked() const
{
foreach (bool v, m_locked) {
if (v)
return true;
}
return false;
}
void QPlatformTextureListWatcher::onLockStatusChanged(bool locked)
{
QPlatformTextureList *tl = static_cast<QPlatformTextureList *>(sender());
m_locked[tl] = locked;
if (!isLocked())
m_backingStore->sync();
}
#endif // QT_NO_OPENGL
static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra)
{
if (!tlw || !tlwExtra || !tlw->testAttribute(Qt::WA_Mapped) || !tlw->isVisible())
@ -941,7 +1030,7 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg
// Nothing to repaint.
if (!isDirty() && store->size().isValid()) {
qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset, widgetTextures, this);
qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset, widgetTexturesFor(tlw, tlw), this);
return;
}
@ -953,45 +1042,6 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg
doSync();
}
#ifndef QT_NO_OPENGL
static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatformTextureList *widgetTextures)
{
QWidgetPrivate *wd = QWidgetPrivate::get(widget);
if (wd->renderToTexture) {
QPlatformTextureList::Flags flags = 0;
if (widget->testAttribute(Qt::WA_AlwaysStackOnTop))
flags |= QPlatformTextureList::StacksOnTop;
const QRect rect(widget->mapTo(tlw, QPoint()), widget->size());
widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags);
}
for (int i = 0; i < wd->children.size(); ++i) {
QWidget *w = qobject_cast<QWidget *>(wd->children.at(i));
if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
findTextureWidgetsRecursively(tlw, w, widgetTextures);
}
}
QPlatformTextureListWatcher::QPlatformTextureListWatcher(QWidgetBackingStore *backingStore)
: m_locked(false),
m_backingStore(backingStore)
{
}
void QPlatformTextureListWatcher::watch(QPlatformTextureList *textureList)
{
connect(textureList, SIGNAL(locked(bool)), SLOT(onLockStatusChanged(bool)));
m_locked = textureList->isLocked();
}
void QPlatformTextureListWatcher::onLockStatusChanged(bool locked)
{
m_locked = locked;
if (!locked)
m_backingStore->sync();
}
#endif // QT_NO_OPENGL
/*!
Synchronizes the backing store, i.e. dirty areas are repainted and flushed.
*/
@ -1019,11 +1069,18 @@ void QWidgetBackingStore::sync()
if (textureListWatcher && !textureListWatcher->isLocked()) {
textureListWatcher->deleteLater();
textureListWatcher = 0;
} else if (widgetTextures && widgetTextures->isLocked()) {
} else if (!tlwExtra->widgetTextures.isEmpty()) {
bool skipSync = false;
foreach (QPlatformTextureList *tl, tlwExtra->widgetTextures) {
if (tl->isLocked()) {
if (!textureListWatcher)
textureListWatcher = new QPlatformTextureListWatcher(this);
if (!textureListWatcher->isLocked())
textureListWatcher->watch(widgetTextures);
textureListWatcher->watch(tl);
skipSync = true;
}
}
if (skipSync) // cannot compose due to widget textures being in use
return;
}
#endif
@ -1117,13 +1174,14 @@ void QWidgetBackingStore::doSync()
dirtyWidgets.clear();
#ifndef QT_NO_OPENGL
delete widgetTextures;
widgetTextures = 0;
if (tlw->d_func()->textureChildSeen) {
widgetTextures = new QPlatformTextureList;
findTextureWidgetsRecursively(tlw, tlw, widgetTextures);
}
qt_window_private(tlw->windowHandle())->compositing = widgetTextures;
// Find all render-to-texture child widgets (including self).
// The search is cut at native widget boundaries, meaning that each native child widget
// has its own list for the subtree below it.
QTLWExtra *tlwExtra = tlw->d_func()->topData();
qDeleteAll(tlwExtra->widgetTextures);
tlwExtra->widgetTextures.clear();
findAllTextureWidgetsRecursively(tlw, tlw);
qt_window_private(tlw->windowHandle())->compositing = false; // will get updated in qt_flush()
fullUpdatePending = false;
#endif
@ -1143,6 +1201,9 @@ void QWidgetBackingStore::doSync()
for (int i = 0; i < paintPending.count(); ++i) {
QWidget *w = paintPending[i];
w->d_func()->sendPaintEvent(w->rect());
QWidget *npw = w->nativeParentWidget();
if (w->internalWinId() || (npw && npw != tlw))
markDirtyOnScreen(w->rect(), w, w->mapTo(tlw, QPoint()));
}
// We might have newly exposed areas on the screen if this function was
@ -1154,18 +1215,23 @@ void QWidgetBackingStore::doSync()
}
#ifndef QT_NO_OPENGL
if (widgetTextures && widgetTextures->count()) {
for (int i = 0; i < widgetTextures->count(); ++i) {
QWidget *w = static_cast<QWidget *>(widgetTextures->source(i));
foreach (QPlatformTextureList *tl, tlwExtra->widgetTextures) {
for (int i = 0; i < tl->count(); ++i) {
QWidget *w = static_cast<QWidget *>(tl->source(i));
if (dirtyRenderToTextureWidgets.contains(w)) {
const QRect rect = widgetTextures->geometry(i); // mapped to the tlw already
const QRect rect = tl->geometry(i); // mapped to the tlw already
dirty += rect;
toClean += rect;
}
}
}
for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i)
resetWidget(dirtyRenderToTextureWidgets.at(i));
for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i) {
QWidget *w = dirtyRenderToTextureWidgets.at(i);
resetWidget(w);
QWidget *npw = w->nativeParentWidget();
if (w->internalWinId() || (npw && npw != tlw))
markDirtyOnScreen(w->rect(), w, w->mapTo(tlw, QPoint()));
}
dirtyRenderToTextureWidgets.clear();
#endif
@ -1235,31 +1301,39 @@ void QWidgetBackingStore::doSync()
*/
void QWidgetBackingStore::flush(QWidget *widget)
{
const bool hasDirtyOnScreenWidgets = dirtyOnScreenWidgets && !dirtyOnScreenWidgets->isEmpty();
bool flushed = false;
// Flush the region in dirtyOnScreen.
if (!dirtyOnScreen.isEmpty()) {
QWidget *target = widget ? widget : tlw;
qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTextures, this);
qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTexturesFor(tlw, tlw), this);
dirtyOnScreen = QRegion();
flushed = true;
}
// Render-to-texture widgets are not in dirtyOnScreen so flush if we have not done it above.
if (!flushed && !hasDirtyOnScreenWidgets) {
#ifndef QT_NO_OPENGL
if (widgetTextures && widgetTextures->count())
return;
if (!tlw->d_func()->topData()->widgetTextures.isEmpty()) {
QPlatformTextureList *tl = widgetTexturesFor(tlw, tlw);
if (tl) {
QWidget *target = widget ? widget : tlw;
qt_flush(target, QRegion(), store, tlw, tlwOffset, tl, this);
}
}
#endif
}
if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty()) {
#ifndef QT_NO_OPENGL
if (widgetTextures && widgetTextures->count()) {
QWidget *target = widget ? widget : tlw;
qt_flush(target, QRegion(), store, tlw, tlwOffset, widgetTextures, this);
}
#endif
if (!hasDirtyOnScreenWidgets)
return;
}
for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) {
QWidget *w = dirtyOnScreenWidgets->at(i);
QWidgetPrivate *wd = w->d_func();
Q_ASSERT(wd->needsFlush);
qt_flush(w, *wd->needsFlush, store, tlw, tlwOffset, 0, this);
QPlatformTextureList *widgetTexturesForNative = wd->textureChildSeen ? widgetTexturesFor(tlw, w) : 0;
qt_flush(w, *wd->needsFlush, store, tlw, tlwOffset, widgetTexturesForNative, this);
*wd->needsFlush = QRegion();
}
dirtyOnScreenWidgets->clear();

View File

@ -71,13 +71,13 @@ class QPlatformTextureListWatcher : public QObject
public:
QPlatformTextureListWatcher(QWidgetBackingStore *backingStore);
void watch(QPlatformTextureList *textureList);
bool isLocked() const { return m_locked; }
bool isLocked() const;
private slots:
void onLockStatusChanged(bool locked);
private:
bool m_locked;
QHash<QPlatformTextureList *, bool> m_locked;
QWidgetBackingStore *m_backingStore;
};
#endif
@ -128,7 +128,6 @@ private:
QVector<QWidget *> dirtyRenderToTextureWidgets;
QVector<QWidget *> *dirtyOnScreenWidgets;
QList<QWidget *> staticWidgets;
QPlatformTextureList *widgetTextures;
QBackingStore *store;
uint fullUpdatePending : 1;
uint updateRequestSent : 1;

View File

@ -265,8 +265,8 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
case PE_IndicatorProgressChunk:
{
bool vertical = false;
if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(opt))
vertical = (pb2->orientation == Qt::Vertical);
if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt))
vertical = pb->orientation == Qt::Vertical;
if (!vertical) {
p->fillRect(opt->rect.x(), opt->rect.y() + 3, opt->rect.width() -2, opt->rect.height() - 6,
opt->palette.brush(QPalette::Highlight));
@ -1085,7 +1085,7 @@ void QCommonStylePrivate::viewItemLayout(const QStyleOptionViewItem *opt, QRect
Uses the same computation than in QTabBar::tabSizeHint
*/
void QCommonStylePrivate::tabLayout(const QStyleOptionTabV3 *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const
void QCommonStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const
{
Q_ASSERT(textRect);
Q_ASSERT(iconRect);
@ -1391,7 +1391,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
case CE_ProgressBar:
if (const QStyleOptionProgressBar *pb
= qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {
QStyleOptionProgressBarV2 subopt = *pb;
QStyleOptionProgressBar subopt = *pb;
subopt.rect = subElementRect(SE_ProgressBarGroove, pb, widget);
proxy()->drawControl(CE_ProgressBarGroove, &subopt, p, widget);
subopt.rect = subElementRect(SE_ProgressBarContents, pb, widget);
@ -1409,10 +1409,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
break;
case CE_ProgressBarLabel:
if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {
bool vertical = false;
if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(opt)) {
vertical = (pb2->orientation == Qt::Vertical);
}
const bool vertical = pb->orientation == Qt::Vertical;
if (!vertical) {
QPalette::ColorRole textRole = QPalette::NoRole;
if ((pb->textAlignment & Qt::AlignCenter) && pb->textVisible
@ -1437,18 +1434,12 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {
QRect rect = pb->rect;
bool vertical = false;
bool inverted = false;
const bool vertical = pb->orientation == Qt::Vertical;
const bool inverted = pb->invertedAppearance;
qint64 minimum = qint64(pb->minimum);
qint64 maximum = qint64(pb->maximum);
qint64 progress = qint64(pb->progress);
// Get extra style options if version 2
const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(opt);
if (pb2) {
vertical = (pb2->orientation == Qt::Vertical);
inverted = pb2->invertedAppearance;
}
QMatrix m;
if (vertical) {
@ -1508,7 +1499,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
int x0 = reverse ? rect.right() - ((unit_width > 1) ? unit_width : 0)
: rect.x();
QStyleOptionProgressBarV2 pbBits = *pb;
QStyleOptionProgressBar pbBits = *pb;
pbBits.rect = rect;
pbBits.palette = pal2;
int myY = pbBits.rect.y();
@ -1864,12 +1855,11 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
break;
case CE_TabBarTabLabel:
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
QStyleOptionTabV3 tabV2(*tab);
QRect tr = tabV2.rect;
bool verticalTabs = tabV2.shape == QTabBar::RoundedEast
|| tabV2.shape == QTabBar::RoundedWest
|| tabV2.shape == QTabBar::TriangularEast
|| tabV2.shape == QTabBar::TriangularWest;
QRect tr = tab->rect;
bool verticalTabs = tab->shape == QTabBar::RoundedEast
|| tab->shape == QTabBar::RoundedWest
|| tab->shape == QTabBar::TriangularEast
|| tab->shape == QTabBar::TriangularWest;
int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget))
@ -1878,7 +1868,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (verticalTabs) {
p->save();
int newX, newY, newRot;
if (tabV2.shape == QTabBar::RoundedEast || tabV2.shape == QTabBar::TriangularEast) {
if (tab->shape == QTabBar::RoundedEast || tab->shape == QTabBar::TriangularEast) {
newX = tr.width() + tr.x();
newY = tr.y();
newRot = 90;
@ -1892,14 +1882,14 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
p->setTransform(m, true);
}
QRect iconRect;
d->tabLayout(&tabV2, widget, &tr, &iconRect);
d->tabLayout(tab, widget, &tr, &iconRect);
tr = proxy()->subElementRect(SE_TabBarTabText, opt, widget); //we compute tr twice because the style may override subElementRect
if (!tabV2.icon.isNull()) {
QPixmap tabIcon = tabV2.icon.pixmap(qt_getWindow(widget), tabV2.iconSize,
(tabV2.state & State_Enabled) ? QIcon::Normal
if (!tab->icon.isNull()) {
QPixmap tabIcon = tab->icon.pixmap(qt_getWindow(widget), tab->iconSize,
(tab->state & State_Enabled) ? QIcon::Normal
: QIcon::Disabled,
(tabV2.state & State_Selected) ? QIcon::On
(tab->state & State_Selected) ? QIcon::On
: QIcon::Off);
p->drawPixmap(iconRect.x(), iconRect.y(), tabIcon);
}
@ -1908,17 +1898,17 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (verticalTabs)
p->restore();
if (tabV2.state & State_HasFocus) {
if (tab->state & State_HasFocus) {
const int OFFSET = 1 + pixelMetric(PM_DefaultFrameWidth);
int x1, x2;
x1 = tabV2.rect.left();
x2 = tabV2.rect.right() - 1;
x1 = tab->rect.left();
x2 = tab->rect.right() - 1;
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*tab);
fropt.rect.setRect(x1 + 1 + OFFSET, tabV2.rect.y() + OFFSET,
x2 - x1 - 2*OFFSET, tabV2.rect.height() - 2*OFFSET);
fropt.rect.setRect(x1 + 1 + OFFSET, tab->rect.y() + OFFSET,
x2 - x1 - 2*OFFSET, tab->rect.height() - 2*OFFSET);
drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
@ -2037,9 +2027,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
}
if (!dwOpt->title.isEmpty()) {
const QStyleOptionDockWidgetV2 *v2
= qstyleoption_cast<const QStyleOptionDockWidgetV2*>(opt);
bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
const bool verticalTitleBar = dwOpt->verticalTitleBar;
if (verticalTitleBar) {
r.setSize(r.size().transposed());
@ -2475,10 +2463,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
case SE_ProgressBarLabel:
if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {
int textw = 0;
bool vertical = false;
if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(opt)) {
vertical = (pb2->orientation == Qt::Vertical);
}
const bool vertical = pb->orientation == Qt::Vertical;
if (!vertical) {
if (pb->textVisible)
textw = qMax(pb->fontMetrics.width(pb->text), pb->fontMetrics.width(QLatin1String("100%"))) + 6;
@ -2731,14 +2716,13 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
break;
case SE_TabBarTabText:
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
QStyleOptionTabV3 tabV3(*tab);
QRect dummyIconRect;
d->tabLayout(&tabV3, widget, &r, &dummyIconRect);
d->tabLayout(tab, widget, &r, &dummyIconRect);
}
break;
case SE_TabBarTabLeftButton:
case SE_TabBarTabRightButton:
if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) {
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
bool selected = tab->state & State_Selected;
int verticalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget);
int horizontalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget);
@ -2927,9 +2911,8 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
= qstyleoption_cast<const QStyleOptionDockWidget*>(opt);
bool canClose = dwOpt == 0 ? true : dwOpt->closable;
bool canFloat = dwOpt == 0 ? false : dwOpt->floatable;
const QStyleOptionDockWidgetV2 *v2
= qstyleoption_cast<const QStyleOptionDockWidgetV2*>(opt);
bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
const bool verticalTitleBar = dwOpt && dwOpt->verticalTitleBar;
// If this is a vertical titlebar, we transpose and work as if it was
// horizontal, then transpose again.

View File

@ -104,7 +104,7 @@ public:
#endif
mutable QIcon tabBarcloseButtonIcon;
#ifndef QT_NO_TABBAR
void tabLayout(const QStyleOptionTabV3 *opt, const QWidget *widget, QRect *textRect, QRect *pixmapRect) const;
void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *pixmapRect) const;
#endif
int animationFps;

View File

@ -192,11 +192,10 @@ void QMenuPrivate::syncPlatformMenu()
return;
QPlatformMenuItem *beforeItem = Q_NULLPTR;
QListIterator<QAction*> it(q->actions());
it.toBack();
while (it.hasPrevious()) {
const QList<QAction*> actions = q->actions();
for (QList<QAction*>::const_reverse_iterator it = actions.rbegin(), end = actions.rend(); it != end; ++it) {
QPlatformMenuItem *menuItem = platformMenu->createMenuItem();
QAction *action = it.previous();
QAction *action = *it;
menuItem->setTag(reinterpret_cast<quintptr>(action));
QObject::connect(menuItem, SIGNAL(activated()), action, SLOT(trigger()), Qt::QueuedConnection);
QObject::connect(menuItem, SIGNAL(hovered()), action, SIGNAL(hovered()), Qt::QueuedConnection);

View File

@ -0,0 +1,12 @@
P2
# A short comment
# A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment A very long comment
24 7
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0
0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0
0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0
0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

View File

@ -224,6 +224,7 @@ void tst_QImageReader::readImage_data()
QTest::newRow("PPM: runners") << QString("runners.ppm") << true << QByteArray("ppm");
QTest::newRow("PPM: test") << QString("test.ppm") << true << QByteArray("ppm");
QTest::newRow("XBM: gnus") << QString("gnus.xbm") << true << QByteArray("xbm");
QTest::newRow("PGM: longcomment") << QString("longcomment.pgm") << true << QByteArray("pgm");
QTest::newRow("JPEG: beavis") << QString("beavis.jpg") << true << QByteArray("jpeg");
QTest::newRow("JPEG: qtbug13653") << QString("qtbug13653-no_eoi.jpg") << true << QByteArray("jpeg");

View File

@ -979,6 +979,20 @@ void tst_Compiler::cxx11_nullptr()
#endif
}
namespace SomeNamespace {
class AdlOnly {
QVector<int> v;
public:
AdlOnly() : v(5) { std::fill_n(v.begin(), v.size(), 42); }
private:
friend QVector<int>::const_iterator begin(const AdlOnly &x) { return x.v.begin(); }
friend QVector<int>::const_iterator end(const AdlOnly &x) { return x.v.end(); }
friend QVector<int>::iterator begin(AdlOnly &x) { return x.v.begin(); }
friend QVector<int>::iterator end(AdlOnly &x) { return x.v.end(); }
};
}
void tst_Compiler::cxx11_range_for()
{
#ifndef Q_COMPILER_RANGE_FOR
@ -998,6 +1012,85 @@ void tst_Compiler::cxx11_range_for()
l << 2;
for (int i : ll)
QCOMPARE(i, 2);
{
const int array[] = { 0, 1, 2, 3, 4 };
int i = 0;
for (const int &e : array)
QCOMPARE(e, array[i++]);
i = 0;
for (int e : array)
QCOMPARE(e, array[i++]);
i = 0;
for (const int e : array)
QCOMPARE(e, array[i++]);
#ifdef Q_COMPILER_AUTO_TYPE
i = 0;
for (const auto &e : array)
QCOMPARE(e, array[i++]);
i = 0;
for (auto &e : array) // auto deducing const
QCOMPARE(e, array[i++]);
i = 0;
for (auto e : array)
QCOMPARE(e, array[i++]);
i = 0;
for (const auto e : array)
QCOMPARE(e, array[i++]);
#endif
}
{
int array[] = { 0, 1, 2, 3, 4 };
const int array2[] = { 10, 11, 12, 13, 14 };
int i = 0;
for (const int &e : array)
QCOMPARE(e, array[i++]);
i = 0;
for (int &e : array)
QCOMPARE(e, array[i++]);
i = 0;
for (int e : array)
QCOMPARE(e, array[i++]);
i = 0;
for (const int e : array)
QCOMPARE(e, array[i++]);
#ifdef Q_COMPILER_AUTO_TYPE
i = 0;
for (const auto &e : array)
QCOMPARE(e, array[i++]);
i = 0;
for (auto &e : array)
QCOMPARE(e, array[i++]);
i = 0;
for (auto e : array)
QCOMPARE(e, array[i++]);
i = 0;
for (const auto e : array)
QCOMPARE(e, array[i++]);
#endif
for (int &e : array)
e += 10;
i = 0;
for (const int &e : array)
QCOMPARE(e, array2[i++]);
}
{
const SomeNamespace::AdlOnly x;
for (const int &e : x)
QCOMPARE(e, 42);
}
{
SomeNamespace::AdlOnly x;
for (const int &e : x)
QCOMPARE(e, 42);
for (int &e : x)
e += 10;
for (const int &e : x)
QCOMPARE(e, 52);
}
#endif
}
@ -1035,24 +1128,88 @@ void tst_Compiler::cxx11_ref_qualifiers()
#endif
}
class MoveDefinedQString {
QString s;
public:
MoveDefinedQString() : s() {}
explicit MoveDefinedQString(const QString &s) : s(s) {}
MoveDefinedQString(const MoveDefinedQString &other) : s(other.s) {}
#ifdef Q_COMPILER_RVALUE_REFS
MoveDefinedQString(MoveDefinedQString &&other) : s(std::move(other.s)) { other.s.clear(); }
MoveDefinedQString &operator=(MoveDefinedQString &&other)
{ s = std::move(other.s); other.s.clear(); return *this; }
#endif
MoveDefinedQString &operator=(const MoveDefinedQString &other) { s = other.s; return *this; }
private:
friend bool operator==(const MoveDefinedQString &lhs, const MoveDefinedQString &rhs)
{ return lhs.s == rhs.s; }
friend bool operator!=(const MoveDefinedQString &lhs, const MoveDefinedQString &rhs)
{ return !operator==(lhs, rhs); }
friend char* toString(const MoveDefinedQString &mds)
{ using namespace QTest; return toString(mds.s); }
};
void tst_Compiler::cxx11_rvalue_refs()
{
#ifndef Q_COMPILER_RVALUE_REFS
QSKIP("Compiler does not support C++11 feature");
#else
// we require std::move:
{
int i = 1;
i = std::move(i);
QString s = "Hello";
QString t = std::move(s);
QCOMPARE(t, QString("Hello"));
MoveDefinedQString s("Hello");
MoveDefinedQString t = std::move(s);
QCOMPARE(t, MoveDefinedQString("Hello"));
QCOMPARE(s, MoveDefinedQString());
s = t;
t = std::move(s);
QCOMPARE(t, QString("Hello"));
QCOMPARE(t, MoveDefinedQString("Hello"));
QCOMPARE(s, MoveDefinedQString());
QString &&r = std::move(s);
QCOMPARE(r, QString("Hello"));
MoveDefinedQString &&r = std::move(t); // no actual move!
QCOMPARE(r, MoveDefinedQString("Hello"));
QCOMPARE(t, MoveDefinedQString("Hello")); // so 't' is unchanged
}
// we require std::forward:
{
MoveDefinedQString s("Hello");
MoveDefinedQString s2 = std::forward<MoveDefinedQString>(s); // forward as rvalue
QCOMPARE(s2, MoveDefinedQString("Hello"));
QCOMPARE(s, MoveDefinedQString());
MoveDefinedQString s3 = std::forward<MoveDefinedQString&>(s2); // forward as lvalue
QCOMPARE(s2, MoveDefinedQString("Hello"));
QCOMPARE(s3, MoveDefinedQString("Hello"));
}
// supported by MSVC only from November 2013 CTP, but only check for VC2015:
# if !defined(Q_CC_MSVC) || defined(Q_CC_INTEL) || _MSC_VER >= 1900 // VS14 == VC2015
// we require automatic generation of move special member functions:
{
struct M { MoveDefinedQString s1, s2; };
M m1 = { MoveDefinedQString("Hello"), MoveDefinedQString("World") };
QCOMPARE(m1.s1, MoveDefinedQString("Hello"));
QCOMPARE(m1.s2, MoveDefinedQString("World"));
M m2 = std::move(m1);
QCOMPARE(m1.s1, MoveDefinedQString());
QCOMPARE(m1.s2, MoveDefinedQString());
QCOMPARE(m2.s1, MoveDefinedQString("Hello"));
QCOMPARE(m2.s2, MoveDefinedQString("World"));
M m3;
QCOMPARE(m3.s1, MoveDefinedQString());
QCOMPARE(m3.s2, MoveDefinedQString());
m3 = std::move(m2);
QCOMPARE(m2.s1, MoveDefinedQString());
QCOMPARE(m2.s2, MoveDefinedQString());
QCOMPARE(m3.s1, MoveDefinedQString("Hello"));
QCOMPARE(m3.s2, MoveDefinedQString("World"));
}
# endif // MSVC < 2015
#endif
}
@ -1265,9 +1422,11 @@ void tst_Compiler::cxx14_decltype_auto()
}
#if __cpp_return_type_deduction >= 201304
auto returnTypeDeduction()
auto returnTypeDeduction(bool choice)
{
if (choice)
return 1U;
return returnTypeDeduction(!choice);
}
#endif
@ -1276,7 +1435,7 @@ void tst_Compiler::cxx14_return_type_deduction()
#if __cpp_return_type_deduction-0 < 201304
QSKIP("Compiler does not support this C++14 feature");
#else
QCOMPARE(returnTypeDeduction(), 1U);
QCOMPARE(returnTypeDeduction(false), 1U);
#endif
}

View File

@ -593,7 +593,7 @@ public:
connect(this, SIGNAL(modelReset()), this, SLOT(modelResetSlot()));
}
void testme()
void testNested()
{
// Only the outermost beginResetModel/endResetModel should
// emit signals.
@ -618,6 +618,14 @@ public:
QCOMPARE(gotReset, true);
}
void testClear() // QTBUG-49404: Basic test whether clear() emits signals.
{
gotAboutToBeReset = gotReset = false;
clear();
QVERIFY(gotAboutToBeReset);
QVERIFY(gotReset);
}
private slots:
void modelAboutToBeResetSlot() { gotAboutToBeReset = true; }
void modelResetSlot() { gotReset = true; }
@ -634,7 +642,8 @@ void tst_QSqlQueryModel::nestedResets()
CHECK_DATABASE(db);
NestedResetsTest t;
t.testme();
t.testClear();
t.testNested();
}
// For task 180617

View File

@ -9,4 +9,4 @@ HEADERS += object1.h \
object7.h \
object8.h \
object9.h
SOURCES += main.cpp
SOURCES += main.cpp needed.cpp

View File

@ -31,6 +31,9 @@
**
****************************************************************************/
#define spurious \
/ #include "needed.cpp"
// if not ignored, symbol needed() won't be available ...
#include <moc_object1.cpp>
/**/ #include <moc_object2.cpp>
@ -49,5 +52,7 @@ static void function2(); /**/
static void function3(); //
#include <moc_object9.cpp>
int main () {}
int main () {
extern int needed(void);
return needed();
}

View File

@ -0,0 +1 @@
extern int needed(void) { return 1; }

View File

@ -57,6 +57,8 @@ private slots:
void asViewport();
void requestUpdate();
void fboRedirect();
void showHide();
void nativeWindow();
};
void tst_QOpenGLWidget::create()
@ -81,7 +83,8 @@ public:
: QOpenGLWidget(parent),
m_initCalled(false), m_paintCalled(false), m_resizeCalled(false),
m_resizeOk(false),
m_w(expectedWidth), m_h(expectedHeight) { }
m_w(expectedWidth), m_h(expectedHeight),
r(1.0f), g(0.0f), b(0.0f) { }
void initializeGL() Q_DECL_OVERRIDE {
m_initCalled = true;
@ -89,13 +92,16 @@ public:
}
void paintGL() Q_DECL_OVERRIDE {
m_paintCalled = true;
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClearColor(r, g, b, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
void resizeGL(int w, int h) Q_DECL_OVERRIDE {
m_resizeCalled = true;
m_resizeOk = w == m_w && h == m_h;
}
void setClearColor(float r, float g, float b) {
this->r = r; this->g = g; this->b = b;
}
bool m_initCalled;
bool m_paintCalled;
@ -103,6 +109,7 @@ public:
bool m_resizeOk;
int m_w;
int m_h;
float r, g, b;
};
void tst_QOpenGLWidget::clearAndGrab()
@ -355,6 +362,69 @@ void tst_QOpenGLWidget::fboRedirect()
QVERIFY(reportedDefaultFbo != widgetFbo);
}
void tst_QOpenGLWidget::showHide()
{
QScopedPointer<ClearWidget> w(new ClearWidget(0, 800, 600));
w->resize(800, 600);
w->show();
QTest::qWaitForWindowExposed(w.data());
w->hide();
QImage image = w->grabFramebuffer();
QVERIFY(!image.isNull());
QCOMPARE(image.width(), w->width());
QCOMPARE(image.height(), w->height());
QVERIFY(image.pixel(30, 40) == qRgb(255, 0, 0));
w->setClearColor(0, 0, 1);
w->show();
QTest::qWaitForWindowExposed(w.data());
image = w->grabFramebuffer();
QVERIFY(!image.isNull());
QCOMPARE(image.width(), w->width());
QCOMPARE(image.height(), w->height());
QVERIFY(image.pixel(30, 40) == qRgb(0, 0, 255));
}
void tst_QOpenGLWidget::nativeWindow()
{
QScopedPointer<ClearWidget> w(new ClearWidget(0, 800, 600));
w->resize(800, 600);
w->show();
w->winId();
QTest::qWaitForWindowExposed(w.data());
QImage image = w->grabFramebuffer();
QVERIFY(!image.isNull());
QCOMPARE(image.width(), w->width());
QCOMPARE(image.height(), w->height());
QVERIFY(image.pixel(30, 40) == qRgb(255, 0, 0));
QVERIFY(w->internalWinId());
// Now as a native child.
QWidget nativeParent;
nativeParent.resize(800, 600);
nativeParent.setAttribute(Qt::WA_NativeWindow);
ClearWidget *child = new ClearWidget(0, 800, 600);
child->setClearColor(0, 1, 0);
child->setParent(&nativeParent);
child->resize(400, 400);
child->move(23, 34);
nativeParent.show();
QTest::qWaitForWindowExposed(&nativeParent);
QVERIFY(nativeParent.internalWinId());
QVERIFY(!child->internalWinId());
image = child->grabFramebuffer();
QVERIFY(!image.isNull());
QCOMPARE(image.width(), child->width());
QCOMPARE(image.height(), child->height());
QVERIFY(image.pixel(30, 40) == qRgb(0, 255, 0));
}
QTEST_MAIN(tst_QOpenGLWidget)
#include "tst_qopenglwidget.moc"

View File

@ -35,13 +35,108 @@
#include <QApplication>
#include <QPushButton>
#include <QMdiArea>
#include <QMdiSubWindow>
#include <QMenu>
#include <QMenuBar>
#include <QMainWindow>
#include <QLCDNumber>
#include <QScrollArea>
#include <QScrollBar>
#include <QTabWidget>
#include <QLabel>
#include <QTimer>
#include <QSurfaceFormat>
#include <QDebug>
#include <private/qwindow_p.h>
class Tools : public QObject
{
Q_OBJECT
public:
Tools(QWidget *root, QWidget *widgetToTurn, const QVector<QWidget *> glwidgets)
: m_root(root), m_widgetToTurn(widgetToTurn), m_glWidgets(glwidgets) { }
void dump();
private slots:
void turnNative();
void hideShowAllGL();
void dumpCompositingStatus();
signals:
void aboutToShowGLWidgets();
private:
void dumpWidget(QWidget *w, int indent = 0);
QWidget *m_root;
QWidget *m_widgetToTurn;
QVector<QWidget *> m_glWidgets;
};
void Tools::turnNative()
{
qDebug("Turning into native");
m_widgetToTurn->winId();
dump();
}
void Tools::hideShowAllGL()
{
if (m_glWidgets[0]->isVisible()) {
qDebug("Hiding all render-to-texture widgets");
foreach (QWidget *w, m_glWidgets)
w->hide();
} else {
qDebug("Showing all render-to-texture widgets");
emit aboutToShowGLWidgets();
foreach (QWidget *w, m_glWidgets)
w->show();
}
}
void Tools::dump()
{
qDebug() << "Widget hierarchy";
dumpWidget(m_root);
qDebug() << "========";
}
void Tools::dumpWidget(QWidget *w, int indent)
{
QString indentStr;
indentStr.fill(' ', indent);
qDebug().noquote() << indentStr << w << "winId =" << w->internalWinId();
foreach (QObject *obj, w->children()) {
if (QWidget *cw = qobject_cast<QWidget *>(obj))
dumpWidget(cw, indent + 4);
}
}
void Tools::dumpCompositingStatus()
{
QWindow *w = m_root->window()->windowHandle();
qDebug() << "Compositing status for" << w << m_root->window() << "is" << QWindowPrivate::get(w)->compositing;
}
class TabWidgetResetter : public QObject
{
Q_OBJECT
public:
TabWidgetResetter(QTabWidget *tw) : m_tw(tw) { }
public slots:
void reset() { m_tw->setCurrentIndex(0); }
private:
QTabWidget *m_tw;
};
int main(int argc, char *argv[])
{
if (argc > 1 && !strcmp(argv[1], "--sharecontext")) {
qDebug("Requesting all contexts to share");
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
}
QApplication a(argc, argv);
QSurfaceFormat format;
@ -53,28 +148,86 @@ int main(int argc, char *argv[])
}
qDebug() << "Requesting" << format;
QMdiArea w;
w.resize(400,400);
QMainWindow wnd;
wnd.setObjectName("Main Window");
wnd.resize(1024, 768);
OpenGLWidget *glw = new OpenGLWidget;
QMdiArea *w = new QMdiArea;
w->setObjectName("MDI area");
w->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
wnd.setCentralWidget(w);
OpenGLWidget *glw = new OpenGLWidget(33, QVector3D(0, 0, 1));
glw->setObjectName("First GL Widget with 33 ms timer");
glw->setFormat(format);
w.addSubWindow(glw);
glw->setMinimumSize(100,100);
glw->setMinimumSize(100, 100);
QMdiSubWindow *sw = w->addSubWindow(glw);
sw->setObjectName("First MDI Sub-Window");
sw->setWindowTitle("33 ms timer");
OpenGLWidget *glw2 = new OpenGLWidget;
OpenGLWidget *glw2 = new OpenGLWidget(16);
glw2->setObjectName("Second GL Widget with 16 ms timer");
glw2->setFormat(format);
glw2->setMinimumSize(100,100);
w.addSubWindow(glw2);
glw2->setMinimumSize(100, 100);
QOpenGLWidget *glw22 = new OpenGLWidget(16);
glw22->setObjectName("Second #2 GLWidget");
glw22->setParent(glw2);
glw22->resize(40, 40);
sw = w->addSubWindow(glw2);
sw->setObjectName("Second MDI Sub-Window");
sw->setWindowTitle("16 ms timer");
OpenGLWidget *glw3 = new OpenGLWidget(0); // trigger updates continuously, no timer
glw3->setObjectName("GL widget in scroll area (possibly native)");
glw3->setFormat(format);
glw3->setFixedSize(600, 600);
QScrollArea *sa = new QScrollArea;
sa->setWidget(glw3);
sa->setMinimumSize(100, 100);
sa->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
sw = w->addSubWindow(sa);
sw->setObjectName("MDI Sub-Window for scroll area");
sw->setWindowTitle("Cont. update");
sw->resize(300, 300);
sa->verticalScrollBar()->setValue(300);
QLCDNumber *lcd = new QLCDNumber;
lcd->display(1337);
lcd->setMinimumSize(300,100);
w.addSubWindow(lcd);
lcd->setMinimumSize(300, 100);
sw = w->addSubWindow(lcd);
sw->setObjectName("MDI Sub-Window for LCD widget");
sw->setWindowTitle("Ordinary widget");
w.show();
QTabWidget *tw = new QTabWidget;
QOpenGLWidget *glw4 = new OpenGLWidget(16, QVector3D(1, 0, 0));
glw4->setObjectName("GL widget in tab widget");
tw->addTab(glw4, "OpenGL");
QLabel *label = new QLabel("Another tab");
tw->addTab(label, "Not OpenGL");
tw->setMinimumSize(100, 100);
sw = w->addSubWindow(tw);
sw->setObjectName("MDI Sub-Window for tab widget");
sw->setWindowTitle("Tabs");
TabWidgetResetter twr(tw);
Tools t(&wnd, glw3, QVector<QWidget *>() << glw << glw2 << glw3 << glw4);
QObject::connect(&t, SIGNAL(aboutToShowGLWidgets()), &twr, SLOT(reset()));
QMenu *toolsMenu = wnd.menuBar()->addMenu("&Tools");
toolsMenu->addAction("&Turn widgets (or some parent) into native", &t, SLOT(turnNative()));
toolsMenu->addAction("&Hide/show all OpenGL widgets", &t, SLOT(hideShowAllGL()));
QTimer compStatusDumpTimer;
QObject::connect(&compStatusDumpTimer, SIGNAL(timeout()), &t, SLOT(dumpCompositingStatus()));
compStatusDumpTimer.start(5000);
wnd.show();
if (glw->isValid())
qDebug() << "Got" << glw->format();
t.dump();
return a.exec();
}
#include "main.moc"

View File

@ -75,16 +75,23 @@ public:
int w,h;
QWidget *q;
int m_interval;
QVector3D m_rotAxis;
};
OpenGLWidget::OpenGLWidget(QWidget *parent)
OpenGLWidget::OpenGLWidget(int interval, const QVector3D &rotAxis, QWidget *parent)
: QOpenGLWidget(parent)
{
d = new OpenGLWidgetPrivate(this);
d.reset(new OpenGLWidgetPrivate(this));
d->m_interval = interval;
d->m_rotAxis = rotAxis;
if (interval > 0) {
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(30);
timer->start(interval);
}
}
OpenGLWidget::~OpenGLWidget()
@ -152,7 +159,8 @@ void OpenGLWidgetPrivate::render()
QMatrix4x4 matrix;
matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f);
matrix.translate(0, 0, -2);
matrix.rotate(100.0f * m_frame / 30/*screen()->refreshRate()*/, 0, 1, 0);
const qreal angle = 100.0f * m_frame / 30;
matrix.rotate(angle, m_rotAxis);
m_program->setUniformValue(m_matrixUniform, matrix);
@ -182,4 +190,7 @@ void OpenGLWidgetPrivate::render()
m_program->release();
++m_frame;
if (m_interval <= 0)
q->update();
}

View File

@ -35,13 +35,14 @@
#define OPENGLWIDGET_H
#include <QtWidgets/QOpenGLWidget>
#include <QtGui/QVector3D>
class OpenGLWidgetPrivate;
class OpenGLWidget : public QOpenGLWidget
{
Q_OBJECT
public:
OpenGLWidget(QWidget *parent = 0);
OpenGLWidget(int interval = 30, const QVector3D &rotAxis = QVector3D(0, 1, 0), QWidget *parent = 0);
~OpenGLWidget();
void initializeGL();
@ -49,7 +50,7 @@ public:
void paintGL();
private:
OpenGLWidgetPrivate *d;
QScopedPointer<OpenGLWidgetPrivate> d;
};
#endif // OPENGLWIDGET_H