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> </uap:VisualElements>
</Application> </Application>
</Applications> </Applications>
$${WINRT_MANIFEST.capabilities}
<Capabilities>
<Capability Name=\"internetClient\" />
</Capabilities>
</Package> </Package>

View File

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

View File

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

View File

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

View File

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

View File

@ -108,6 +108,10 @@
INDENT = "$$escape_expand(\\r\\n) " 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.) # 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 = $$unique(WINRT_MANIFEST.capabilities)
WINRT_MANIFEST.capabilities_device = $$unique(WINRT_MANIFEST.capabilities_device) WINRT_MANIFEST.capabilities_device = $$unique(WINRT_MANIFEST.capabilities_device)

View File

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

View File

@ -67,5 +67,9 @@ contains(QT_CONFIG, system-zlib) {
DEFINES += FT_CONFIG_OPTION_SYSTEM_ZLIB DEFINES += FT_CONFIG_OPTION_SYSTEM_ZLIB
include($$PWD/../zlib_dependency.pri) 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 DEFINES += TT_CONFIG_OPTION_SUBPIXEL_HINTING

View File

@ -66,8 +66,12 @@
#ifndef QT_NO_QOBJECT #ifndef QT_NO_QOBJECT
#if defined(Q_OS_UNIX) #if defined(Q_OS_UNIX)
# if !defined(QT_NO_GLIB) # if defined(Q_OS_OSX)
# include "qeventdispatcher_glib_p.h" # include "qeventdispatcher_cf_p.h"
# else
# if !defined(QT_NO_GLIB)
# include "qeventdispatcher_glib_p.h"
# endif
# endif # endif
# include "qeventdispatcher_unix_p.h" # include "qeventdispatcher_unix_p.h"
#endif #endif
@ -469,12 +473,21 @@ void QCoreApplicationPrivate::createEventDispatcher()
{ {
Q_Q(QCoreApplication); Q_Q(QCoreApplication);
#if defined(Q_OS_UNIX) #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()) if (qEnvironmentVariableIsEmpty("QT_NO_GLIB") && QEventDispatcherGlib::versionSupported())
eventDispatcher = new QEventDispatcherGlib(q); eventDispatcher = new QEventDispatcherGlib(q);
else else
# endif
eventDispatcher = new QEventDispatcherUNIX(q); eventDispatcher = new QEventDispatcherUNIX(q);
# else
eventDispatcher = new QEventDispatcherUNIX(q);
# endif
#elif defined(Q_OS_WINRT) #elif defined(Q_OS_WINRT)
eventDispatcher = new QEventDispatcherWinRT(q); eventDispatcher = new QEventDispatcherWinRT(q);
#elif defined(Q_OS_WIN) #elif defined(Q_OS_WIN)
@ -613,8 +626,9 @@ void QCoreApplicationPrivate::initLocale()
The command line arguments which are passed to QCoreApplication's The command line arguments which are passed to QCoreApplication's
constructor should be accessed using the arguments() function. 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. For more advanced command line option handling, create a QCommandLineParser.

View File

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

View File

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

View File

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

View File

@ -36,9 +36,14 @@
#include "qplatformdefs.h" #include "qplatformdefs.h"
#include <private/qcoreapplication_p.h> #include <private/qcoreapplication_p.h>
#include <private/qcore_unix_p.h>
#if !defined(QT_NO_GLIB) #if defined(Q_OS_OSX)
# include "../kernel/qeventdispatcher_glib_p.h" # include <private/qeventdispatcher_cf_p.h>
#else
# if !defined(QT_NO_GLIB)
# include "../kernel/qeventdispatcher_glib_p.h"
# endif
#endif #endif
#include <private/qeventdispatcher_unix_p.h> #include <private/qeventdispatcher_unix_p.h>
@ -243,14 +248,23 @@ typedef void*(*QtThreadCallback)(void*);
void QThreadPrivate::createEventDispatcher(QThreadData *data) 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") if (qEnvironmentVariableIsEmpty("QT_NO_GLIB")
&& qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB") && qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB")
&& QEventDispatcherGlib::versionSupported()) && QEventDispatcherGlib::versionSupported())
data->eventDispatcher.storeRelease(new QEventDispatcherGlib); data->eventDispatcher.storeRelease(new QEventDispatcherGlib);
else else
#endif data->eventDispatcher.storeRelease(new QEventDispatcherUNIX);
#else
data->eventDispatcher.storeRelease(new QEventDispatcherUNIX); data->eventDispatcher.storeRelease(new QEventDispatcherUNIX);
#endif
data->eventDispatcher.load()->startingUp(); data->eventDispatcher.load()->startingUp();
} }

View File

@ -48,6 +48,8 @@
#endif #endif
#ifdef Q_OS_WINRT #ifdef Q_OS_WINRT
#include <qfunctions_winrt.h>
#include <wrl.h> #include <wrl.h>
#include <windows.foundation.h> #include <windows.foundation.h>
#include <windows.foundation.collections.h> #include <windows.foundation.collections.h>
@ -644,21 +646,53 @@ QVariant QSystemLocalePrivate::uiLanguages()
} }
ComPtr<ABI::Windows::Foundation::Collections::IVectorView<HSTRING> > languageList; ComPtr<ABI::Windows::Foundation::Collections::IVectorView<HSTRING> > languageList;
appLanguagesStatics->get_ManifestLanguages(&languageList); // 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.
if (!languageList) HRESULT hr = appLanguagesStatics->get_Languages(&languageList);
return QStringList(); Q_ASSERT_SUCCEEDED(hr);
unsigned int size; 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) { for (unsigned int i = 0; i < size; ++i) {
HString language; HString language;
languageList->GetAt(i, language.GetAddressOf()); hr = languageList->GetAt(i, language.GetAddressOf());
Q_ASSERT_SUCCEEDED(hr);
UINT32 length; UINT32 length;
PCWSTR rawString = language.GetRawBuffer(&length); PCWSTR rawString = language.GetRawBuffer(&length);
result << QString::fromWCharArray(rawString, 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; return result;
#endif // Q_OS_WINRT #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 /*! \fn QStringRef QXmlStreamEntityDeclaration::name() const
Returns the entity name. Returns the entity name.

View File

@ -53,13 +53,37 @@ public:
inline QXmlStreamStringRef(const QStringRef &aString) inline QXmlStreamStringRef(const QStringRef &aString)
:m_string(aString.string()?*aString.string():QString()), m_position(aString.position()), m_size(aString.size()){} :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(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 void clear() { m_string.clear(); m_position = m_size = 0; }
inline operator QStringRef() const { return QStringRef(&m_string, m_position, m_size); } inline operator QStringRef() const { return QStringRef(&m_string, m_position, m_size); }
inline const QString *string() const { return &m_string; } inline const QString *string() const { return &m_string; }
inline int position() const { return m_position; } inline int position() const { return m_position; }
inline int size() const { return m_size; } inline int size() const { return m_size; }
}; };
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QXmlStreamStringRef)
class QXmlStreamReaderPrivate; class QXmlStreamReaderPrivate;

View File

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

View File

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

View File

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

View File

@ -224,16 +224,16 @@ static inline QRect deviceRect(const QRect &rect, QWindow *window)
return deviceRect; 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; return region;
QVector<QRect> rects; QVector<QRect> rects;
const QVector<QRect> regionRects = region.rects(); const QVector<QRect> regionRects = region.rects();
rects.reserve(regionRects.count()); rects.reserve(regionRects.count());
foreach (const QRect &rect, regionRects) foreach (const QRect &rect, regionRects)
rects.append(deviceRect(rect, window)); rects.append(deviceRect(rect.translated(offset), window));
QRegion deviceRegion; QRegion deviceRegion;
deviceRegion.setRects(rects.constData(), rects.count()); deviceRegion.setRects(rects.constData(), rects.count());
@ -246,10 +246,12 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)
topLeftRect.width(), topLeftRect.height()); topLeftRect.width(), topLeftRect.height());
} }
static void blit(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect, static void blitTextureForWidget(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect,
QOpenGLTextureBlitter *blitter) 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); QRect clipRect = textures->clipRect(idx);
if (clipRect.isEmpty()) if (clipRect.isEmpty())
clipRect = QRect(QPoint(0, 0), rectInWindow.size()); 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 and composes using OpenGL. May be reimplemented in subclasses if there
is a more efficient native way to do it. 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, void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &region,
@ -282,7 +286,8 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
QPlatformTextureList *textures, QOpenGLContext *context, QPlatformTextureList *textures, QOpenGLContext *context,
bool translucentBackground) bool translucentBackground)
{ {
Q_UNUSED(offset); if (!qt_window_private(window)->receivedExpose)
return;
if (!context->makeCurrent(window)) { if (!context->makeCurrent(window)) {
qWarning("composeAndFlush: makeCurrent() failed"); qWarning("composeAndFlush: makeCurrent() failed");
@ -306,7 +311,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
// Textures for renderToTexture widgets. // Textures for renderToTexture widgets.
for (int i = 0; i < textures->count(); ++i) { for (int i = 0; i < textures->count(); ++i) {
if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) 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); funcs->glEnable(GL_BLEND);
@ -348,17 +353,26 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
textureId = d_ptr->textureId; textureId = d_ptr->textureId;
} else { } else {
TextureFlags flags = 0; 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; d_ptr->needsSwizzle = (flags & TextureSwizzle) != 0;
if (flags & TextureFlip) if (flags & TextureFlip)
origin = QOpenGLTextureBlitter::OriginBottomLeft; origin = QOpenGLTextureBlitter::OriginBottomLeft;
} }
if (textureId) { if (textureId) {
QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(QRect(QPoint(), d_ptr->textureSize), deviceWindowRect);
if (d_ptr->needsSwizzle) if (d_ptr->needsSwizzle)
d_ptr->blitter->setSwizzleRB(true); 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) if (d_ptr->needsSwizzle)
d_ptr->blitter->setSwizzleRB(false); 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. // Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set.
for (int i = 0; i < textures->count(); ++i) { for (int i = 0; i < textures->count(); ++i) {
if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) 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); 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 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. 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 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. inside the line, taking account of the \a edge.
If \a cursorPos is not a valid cursor position, the nearest valid 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. point to this valid cursor position.
\sa xToCursor() \sa xToCursor()

View File

@ -254,6 +254,10 @@ void QHttpNetworkConnectionChannel::handleUnexpectedEOF()
close(); close();
reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::RemoteHostClosedError, socket); reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::RemoteHostClosedError, socket);
emit reply->finishedWithError(QNetworkReply::RemoteHostClosedError, reply->d_func()->errorString); 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); QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
} else { } else {
reconnectAttempts--; reconnectAttempts--;

View File

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

View File

@ -89,6 +89,9 @@ static QNetworkInterfacePrivate *interfaceFromProfile(IConnectionProfile *profil
ComPtr<INetworkAdapter> adapter; ComPtr<INetworkAdapter> adapter;
hr = profile->get_NetworkAdapter(&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); Q_ASSERT_SUCCEEDED(hr);
UINT32 type; UINT32 type;
hr = adapter->get_IanaInterfaceType(&type); hr = adapter->get_IanaInterfaceType(&type);

View File

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

View File

@ -84,6 +84,15 @@ typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC) (EGLDispla
typedef void *EGLStreamKHR; typedef void *EGLStreamKHR;
typedef quint64 EGLuint64KHR; typedef quint64 EGLuint64KHR;
#define EGL_NO_STREAM_KHR ((EGLStreamKHR)0) #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 EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value); typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);

View File

@ -43,6 +43,7 @@
#include <qplatformdefs.h> #include <qplatformdefs.h>
#include <private/qcore_unix_p.h> // overrides QT_OPEN #include <private/qcore_unix_p.h> // overrides QT_OPEN
#include <private/qhighdpiscaling_p.h>
#include <errno.h> #include <errno.h>
@ -141,7 +142,8 @@ bool QEvdevMouseHandler::getHardwareMaximum()
m_hardwareHeight = absInfo.maximum - absInfo.minimum; 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_hardwareScalerX = static_cast<qreal>(m_hardwareWidth) / (g.right() - g.left());
m_hardwareScalerY = static_cast<qreal>(m_hardwareHeight) / (g.bottom() - g.top()); m_hardwareScalerY = static_cast<qreal>(m_hardwareHeight) / (g.bottom() - g.top());

View File

@ -41,6 +41,7 @@
#include <QtPlatformSupport/private/qdevicediscovery_p.h> #include <QtPlatformSupport/private/qdevicediscovery_p.h>
#include <private/qguiapplication_p.h> #include <private/qguiapplication_p.h>
#include <private/qinputdevicemanager_p_p.h> #include <private/qinputdevicemanager_p_p.h>
#include <private/qhighdpiscaling_p.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -106,7 +107,8 @@ QEvdevMouseManager::~QEvdevMouseManager()
void QEvdevMouseManager::clampPosition() void QEvdevMouseManager::clampPosition()
{ {
// clamp to screen geometry // 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()) if (m_x + m_xoffset < g.left())
m_x = g.left() - m_xoffset; m_x = g.left() - m_xoffset;
else if (m_x + m_xoffset > g.right()) else if (m_x + m_xoffset > g.right())

View File

@ -36,6 +36,7 @@
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
#include <QtGui/QScreen> #include <QtGui/QScreen>
#include <qpa/qwindowsysteminterface.h> #include <qpa/qwindowsysteminterface.h>
#include <private/qhighdpiscaling_p.h>
QT_BEGIN_NAMESPACE 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 dx = libinput_event_pointer_get_dx(e);
const double dy = libinput_event_pointer_get_dy(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.setX(qBound(g.left(), qRound(m_pos.x() + dx), g.right()));
m_pos.setY(qBound(g.top(), qRound(m_pos.y() + dy), g.bottom())); 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) 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.setX(qBound(g.left(), pos.x(), g.right()));
m_pos.setY(qBound(g.top(), pos.y(), g.bottom())); 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; ComPtr<INetworkAdapter> adapter;
hr = profile->get_NetworkAdapter(&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); Q_ASSERT_SUCCEEDED(hr);
GUID id; GUID id;
hr = adapter->get_NetworkAdapterId(&id); hr = adapter->get_NetworkAdapterId(&id);

View File

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

View File

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

View File

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

View File

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

View File

@ -55,6 +55,7 @@ public:
QSizeF physicalSize() const Q_DECL_OVERRIDE; QSizeF physicalSize() const Q_DECL_OVERRIDE;
QDpi logicalDpi() 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 nativeOrientation() const Q_DECL_OVERRIDE;
Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE; Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE;

View File

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

View File

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

View File

@ -57,9 +57,9 @@
}, },
{ {
"id": 5, "id": 5,
"description": "Intel GMA 3150 crashes (QTBUG-43243)", "description": "Intel GMA 3150 (QTBUG-43243), Mobile Intel 945GM (QTBUG-47435) crash",
"vendor_id": "0x8086", "vendor_id": "0x8086",
"device_id": [ "0xA001", "0xA011" ], "device_id": [ "0xA001", "0xA011", "0x27A0" ],
"os": { "os": {
"type": "win" "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) { if ((flags & Qt::FramelessWindowHint) && QWindowsWindow::setWindowLayered(rw->handle(), flags, hasAlpha, rw->opacity()) && hasAlpha) {
// Windows with alpha: Use blend function to update. // Windows with alpha: Use blend function to update.
QRect r = QHighDpi::toNativePixels(window->frameGeometry(), window); 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); QRect dirtyRect = br.translated(offset + frameOffset);
SIZE size = {r.width(), r.height()}; SIZE size = {r.width(), r.height()};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -645,12 +645,6 @@ void QOpenGLWidgetPaintDevice::ensureActiveTarget()
GLuint QOpenGLWidgetPrivate::textureId() const 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); return resolvedFbo ? resolvedFbo->texture() : (fbo ? fbo->texture() : 0);
} }

View File

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

View File

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

View File

@ -79,7 +79,6 @@ void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion &region, QBack
Q_ASSERT(widget); Q_ASSERT(widget);
Q_ASSERT(backingStore); Q_ASSERT(backingStore);
Q_ASSERT(tlw); Q_ASSERT(tlw);
#if !defined(QT_NO_PAINT_DEBUG) #if !defined(QT_NO_PAINT_DEBUG)
static int flushUpdate = qEnvironmentVariableIntValue("QT_FLUSH_UPDATE"); static int flushUpdate = qEnvironmentVariableIntValue("QT_FLUSH_UPDATE");
if (flushUpdate > 0) if (flushUpdate > 0)
@ -105,13 +104,17 @@ void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion &region, QBack
#ifndef QT_NO_OPENGL #ifndef QT_NO_OPENGL
if (widgetTextures) { if (widgetTextures) {
Q_ASSERT(!widgetTextures->isEmpty());
qt_window_private(tlw->windowHandle())->compositing = true;
widget->window()->d_func()->sendComposeStatus(widget->window(), false); widget->window()->d_func()->sendComposeStatus(widget->window(), false);
// A window may have alpha even when the app did not request // A window may have alpha even when the app did not request
// WA_TranslucentBackground. Therefore the compositor needs to know whether the app intends // 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. // to rely on translucency, in order to decide if it should clear to transparent or opaque.
const bool translucentBackground = widget->testAttribute(Qt::WA_TranslucentBackground); 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, 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); widget->window()->d_func()->sendComposeStatus(widget->window(), true);
} else } else
#endif #endif
@ -741,7 +744,6 @@ void QWidgetBackingStore::updateLists(QWidget *cur)
QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel) QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
: tlw(topLevel), : tlw(topLevel),
dirtyOnScreenWidgets(0), dirtyOnScreenWidgets(0),
widgetTextures(0),
fullUpdatePending(0), fullUpdatePending(0),
updateRequestSent(0), updateRequestSent(0),
textureListWatcher(0), textureListWatcher(0),
@ -761,9 +763,6 @@ QWidgetBackingStore::~QWidgetBackingStore()
for (int c = 0; c < dirtyRenderToTextureWidgets.size(); ++c) for (int c = 0; c < dirtyRenderToTextureWidgets.size(); ++c)
resetWidget(dirtyRenderToTextureWidgets.at(c)); resetWidget(dirtyRenderToTextureWidgets.at(c));
#ifndef QT_NO_OPENGL
delete widgetTextures;
#endif
delete dirtyOnScreenWidgets; delete dirtyOnScreenWidgets;
} }
@ -792,8 +791,9 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
destRect = destRect.translated(dx, dy).intersected(clipR); destRect = destRect.translated(dx, dy).intersected(clipR);
const QRect sourceRect(destRect.translated(-dx, -dy)); const QRect sourceRect(destRect.translated(-dx, -dy));
const QRect parentRect(rect & clipR); const QRect parentRect(rect & clipR);
const bool nativeWithTextureChild = textureChildSeen && q->internalWinId();
bool accelerateMove = accelEnv && isOpaque bool accelerateMove = accelEnv && isOpaque && !nativeWithTextureChild
#ifndef QT_NO_GRAPHICSVIEW #ifndef QT_NO_GRAPHICSVIEW
// No accelerate move for proxy widgets. // No accelerate move for proxy widgets.
&& !tlw->d_func()->extra->proxyWidget && !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) static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra)
{ {
if (!tlw || !tlwExtra || !tlw->testAttribute(Qt::WA_Mapped) || !tlw->isVisible()) 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. // Nothing to repaint.
if (!isDirty() && store->size().isValid()) { 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; return;
} }
@ -953,45 +1042,6 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg
doSync(); 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. Synchronizes the backing store, i.e. dirty areas are repainted and flushed.
*/ */
@ -1019,12 +1069,19 @@ void QWidgetBackingStore::sync()
if (textureListWatcher && !textureListWatcher->isLocked()) { if (textureListWatcher && !textureListWatcher->isLocked()) {
textureListWatcher->deleteLater(); textureListWatcher->deleteLater();
textureListWatcher = 0; textureListWatcher = 0;
} else if (widgetTextures && widgetTextures->isLocked()) { } else if (!tlwExtra->widgetTextures.isEmpty()) {
if (!textureListWatcher) bool skipSync = false;
textureListWatcher = new QPlatformTextureListWatcher(this); foreach (QPlatformTextureList *tl, tlwExtra->widgetTextures) {
if (!textureListWatcher->isLocked()) if (tl->isLocked()) {
textureListWatcher->watch(widgetTextures); if (!textureListWatcher)
return; textureListWatcher = new QPlatformTextureListWatcher(this);
if (!textureListWatcher->isLocked())
textureListWatcher->watch(tl);
skipSync = true;
}
}
if (skipSync) // cannot compose due to widget textures being in use
return;
} }
#endif #endif
@ -1117,13 +1174,14 @@ void QWidgetBackingStore::doSync()
dirtyWidgets.clear(); dirtyWidgets.clear();
#ifndef QT_NO_OPENGL #ifndef QT_NO_OPENGL
delete widgetTextures; // Find all render-to-texture child widgets (including self).
widgetTextures = 0; // The search is cut at native widget boundaries, meaning that each native child widget
if (tlw->d_func()->textureChildSeen) { // has its own list for the subtree below it.
widgetTextures = new QPlatformTextureList; QTLWExtra *tlwExtra = tlw->d_func()->topData();
findTextureWidgetsRecursively(tlw, tlw, widgetTextures); qDeleteAll(tlwExtra->widgetTextures);
} tlwExtra->widgetTextures.clear();
qt_window_private(tlw->windowHandle())->compositing = widgetTextures; findAllTextureWidgetsRecursively(tlw, tlw);
qt_window_private(tlw->windowHandle())->compositing = false; // will get updated in qt_flush()
fullUpdatePending = false; fullUpdatePending = false;
#endif #endif
@ -1143,6 +1201,9 @@ void QWidgetBackingStore::doSync()
for (int i = 0; i < paintPending.count(); ++i) { for (int i = 0; i < paintPending.count(); ++i) {
QWidget *w = paintPending[i]; QWidget *w = paintPending[i];
w->d_func()->sendPaintEvent(w->rect()); 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 // We might have newly exposed areas on the screen if this function was
@ -1154,18 +1215,23 @@ void QWidgetBackingStore::doSync()
} }
#ifndef QT_NO_OPENGL #ifndef QT_NO_OPENGL
if (widgetTextures && widgetTextures->count()) { foreach (QPlatformTextureList *tl, tlwExtra->widgetTextures) {
for (int i = 0; i < widgetTextures->count(); ++i) { for (int i = 0; i < tl->count(); ++i) {
QWidget *w = static_cast<QWidget *>(widgetTextures->source(i)); QWidget *w = static_cast<QWidget *>(tl->source(i));
if (dirtyRenderToTextureWidgets.contains(w)) { 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; dirty += rect;
toClean += rect; toClean += rect;
} }
} }
} }
for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i) for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i) {
resetWidget(dirtyRenderToTextureWidgets.at(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(); dirtyRenderToTextureWidgets.clear();
#endif #endif
@ -1235,31 +1301,39 @@ void QWidgetBackingStore::doSync()
*/ */
void QWidgetBackingStore::flush(QWidget *widget) void QWidgetBackingStore::flush(QWidget *widget)
{ {
const bool hasDirtyOnScreenWidgets = dirtyOnScreenWidgets && !dirtyOnScreenWidgets->isEmpty();
bool flushed = false;
// Flush the region in dirtyOnScreen.
if (!dirtyOnScreen.isEmpty()) { if (!dirtyOnScreen.isEmpty()) {
QWidget *target = widget ? widget : tlw; 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(); 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 #ifndef QT_NO_OPENGL
if (widgetTextures && widgetTextures->count()) if (!tlw->d_func()->topData()->widgetTextures.isEmpty()) {
return; QPlatformTextureList *tl = widgetTexturesFor(tlw, tlw);
if (tl) {
QWidget *target = widget ? widget : tlw;
qt_flush(target, QRegion(), store, tlw, tlwOffset, tl, this);
}
}
#endif #endif
} }
if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty()) { if (!hasDirtyOnScreenWidgets)
#ifndef QT_NO_OPENGL
if (widgetTextures && widgetTextures->count()) {
QWidget *target = widget ? widget : tlw;
qt_flush(target, QRegion(), store, tlw, tlwOffset, widgetTextures, this);
}
#endif
return; return;
}
for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) { for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) {
QWidget *w = dirtyOnScreenWidgets->at(i); QWidget *w = dirtyOnScreenWidgets->at(i);
QWidgetPrivate *wd = w->d_func(); QWidgetPrivate *wd = w->d_func();
Q_ASSERT(wd->needsFlush); 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(); *wd->needsFlush = QRegion();
} }
dirtyOnScreenWidgets->clear(); dirtyOnScreenWidgets->clear();

View File

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

View File

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

View File

@ -104,7 +104,7 @@ public:
#endif #endif
mutable QIcon tabBarcloseButtonIcon; mutable QIcon tabBarcloseButtonIcon;
#ifndef QT_NO_TABBAR #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 #endif
int animationFps; int animationFps;

View File

@ -192,11 +192,10 @@ void QMenuPrivate::syncPlatformMenu()
return; return;
QPlatformMenuItem *beforeItem = Q_NULLPTR; QPlatformMenuItem *beforeItem = Q_NULLPTR;
QListIterator<QAction*> it(q->actions()); const QList<QAction*> actions = q->actions();
it.toBack(); for (QList<QAction*>::const_reverse_iterator it = actions.rbegin(), end = actions.rend(); it != end; ++it) {
while (it.hasPrevious()) {
QPlatformMenuItem *menuItem = platformMenu->createMenuItem(); QPlatformMenuItem *menuItem = platformMenu->createMenuItem();
QAction *action = it.previous(); QAction *action = *it;
menuItem->setTag(reinterpret_cast<quintptr>(action)); menuItem->setTag(reinterpret_cast<quintptr>(action));
QObject::connect(menuItem, SIGNAL(activated()), action, SLOT(trigger()), Qt::QueuedConnection); QObject::connect(menuItem, SIGNAL(activated()), action, SLOT(trigger()), Qt::QueuedConnection);
QObject::connect(menuItem, SIGNAL(hovered()), action, SIGNAL(hovered()), 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: runners") << QString("runners.ppm") << true << QByteArray("ppm");
QTest::newRow("PPM: test") << QString("test.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("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: beavis") << QString("beavis.jpg") << true << QByteArray("jpeg");
QTest::newRow("JPEG: qtbug13653") << QString("qtbug13653-no_eoi.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 #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() void tst_Compiler::cxx11_range_for()
{ {
#ifndef Q_COMPILER_RANGE_FOR #ifndef Q_COMPILER_RANGE_FOR
@ -998,6 +1012,85 @@ void tst_Compiler::cxx11_range_for()
l << 2; l << 2;
for (int i : ll) for (int i : ll)
QCOMPARE(i, 2); 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 #endif
} }
@ -1035,24 +1128,88 @@ void tst_Compiler::cxx11_ref_qualifiers()
#endif #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() void tst_Compiler::cxx11_rvalue_refs()
{ {
#ifndef Q_COMPILER_RVALUE_REFS #ifndef Q_COMPILER_RVALUE_REFS
QSKIP("Compiler does not support C++11 feature"); QSKIP("Compiler does not support C++11 feature");
#else #else
int i = 1; // we require std::move:
i = std::move(i); {
int i = 1;
i = std::move(i);
QString s = "Hello"; MoveDefinedQString s("Hello");
QString t = std::move(s); MoveDefinedQString t = std::move(s);
QCOMPARE(t, QString("Hello")); QCOMPARE(t, MoveDefinedQString("Hello"));
QCOMPARE(s, MoveDefinedQString());
s = t; s = t;
t = std::move(s); t = std::move(s);
QCOMPARE(t, QString("Hello")); QCOMPARE(t, MoveDefinedQString("Hello"));
QCOMPARE(s, MoveDefinedQString());
QString &&r = std::move(s); MoveDefinedQString &&r = std::move(t); // no actual move!
QCOMPARE(r, QString("Hello")); 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 #endif
} }
@ -1265,9 +1422,11 @@ void tst_Compiler::cxx14_decltype_auto()
} }
#if __cpp_return_type_deduction >= 201304 #if __cpp_return_type_deduction >= 201304
auto returnTypeDeduction() auto returnTypeDeduction(bool choice)
{ {
return 1U; if (choice)
return 1U;
return returnTypeDeduction(!choice);
} }
#endif #endif
@ -1276,7 +1435,7 @@ void tst_Compiler::cxx14_return_type_deduction()
#if __cpp_return_type_deduction-0 < 201304 #if __cpp_return_type_deduction-0 < 201304
QSKIP("Compiler does not support this C++14 feature"); QSKIP("Compiler does not support this C++14 feature");
#else #else
QCOMPARE(returnTypeDeduction(), 1U); QCOMPARE(returnTypeDeduction(false), 1U);
#endif #endif
} }

View File

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

View File

@ -9,4 +9,4 @@ HEADERS += object1.h \
object7.h \ object7.h \
object8.h \ object8.h \
object9.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_object1.cpp>
/**/ #include <moc_object2.cpp> /**/ #include <moc_object2.cpp>
@ -49,5 +52,7 @@ static void function2(); /**/
static void function3(); // static void function3(); //
#include <moc_object9.cpp> #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 asViewport();
void requestUpdate(); void requestUpdate();
void fboRedirect(); void fboRedirect();
void showHide();
void nativeWindow();
}; };
void tst_QOpenGLWidget::create() void tst_QOpenGLWidget::create()
@ -81,7 +83,8 @@ public:
: QOpenGLWidget(parent), : QOpenGLWidget(parent),
m_initCalled(false), m_paintCalled(false), m_resizeCalled(false), m_initCalled(false), m_paintCalled(false), m_resizeCalled(false),
m_resizeOk(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 { void initializeGL() Q_DECL_OVERRIDE {
m_initCalled = true; m_initCalled = true;
@ -89,13 +92,16 @@ public:
} }
void paintGL() Q_DECL_OVERRIDE { void paintGL() Q_DECL_OVERRIDE {
m_paintCalled = true; m_paintCalled = true;
glClearColor(1.0f, 0.0f, 0.0f, 1.0f); glClearColor(r, g, b, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
} }
void resizeGL(int w, int h) Q_DECL_OVERRIDE { void resizeGL(int w, int h) Q_DECL_OVERRIDE {
m_resizeCalled = true; m_resizeCalled = true;
m_resizeOk = w == m_w && h == m_h; 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_initCalled;
bool m_paintCalled; bool m_paintCalled;
@ -103,6 +109,7 @@ public:
bool m_resizeOk; bool m_resizeOk;
int m_w; int m_w;
int m_h; int m_h;
float r, g, b;
}; };
void tst_QOpenGLWidget::clearAndGrab() void tst_QOpenGLWidget::clearAndGrab()
@ -355,6 +362,69 @@ void tst_QOpenGLWidget::fboRedirect()
QVERIFY(reportedDefaultFbo != widgetFbo); 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) QTEST_MAIN(tst_QOpenGLWidget)
#include "tst_qopenglwidget.moc" #include "tst_qopenglwidget.moc"

View File

@ -35,13 +35,108 @@
#include <QApplication> #include <QApplication>
#include <QPushButton> #include <QPushButton>
#include <QMdiArea> #include <QMdiArea>
#include <QMdiSubWindow>
#include <QMenu>
#include <QMenuBar>
#include <QMainWindow>
#include <QLCDNumber> #include <QLCDNumber>
#include <QScrollArea>
#include <QScrollBar>
#include <QTabWidget>
#include <QLabel>
#include <QTimer> #include <QTimer>
#include <QSurfaceFormat> #include <QSurfaceFormat>
#include <QDebug> #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[]) 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); QApplication a(argc, argv);
QSurfaceFormat format; QSurfaceFormat format;
@ -53,28 +148,86 @@ int main(int argc, char *argv[])
} }
qDebug() << "Requesting" << format; qDebug() << "Requesting" << format;
QMdiArea w; QMainWindow wnd;
w.resize(400,400); 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); 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->setFormat(format);
glw2->setMinimumSize(100,100); glw2->setMinimumSize(100, 100);
w.addSubWindow(glw2); 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; QLCDNumber *lcd = new QLCDNumber;
lcd->display(1337); lcd->display(1337);
lcd->setMinimumSize(300,100); lcd->setMinimumSize(300, 100);
w.addSubWindow(lcd); 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()) if (glw->isValid())
qDebug() << "Got" << glw->format(); qDebug() << "Got" << glw->format();
t.dump();
return a.exec(); return a.exec();
} }
#include "main.moc"

View File

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

View File

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