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

Conflicts:
	src/gui/painting/painting.pri
	src/plugins/platforms/xcb/qxcbconnection.cpp
	tests/auto/corelib/thread/qthreadstorage/qthreadstorage.pro
	tests/auto/corelib/tools/qlocale/test/test.pro
	tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
	tools/configure/environment.cpp

Change-Id: I9c40f458b89b2c206de2d2c24e90b5f679c93495
This commit is contained in:
Liang Qi 2015-12-18 08:37:31 +01:00
commit beb65dcd79
141 changed files with 2037 additions and 627 deletions

View File

@ -764,7 +764,7 @@ while ( @ARGV ) {
$var = "version";
$val = shift @ARGV;
} elsif($arg =~/^-/) {
print STDERR "Unknown option: $arg\n\n" if (!$var);
print STDERR "ERROR: Unknown option: $arg\n\n" if (!$var);
showUsage();
} else {
$basedir = locateSyncProfile($arg);
@ -777,7 +777,7 @@ while ( @ARGV ) {
#do something
if(!$var || $var eq "show_help") {
print STDERR "Unknown option: $arg\n\n" if (!$var);
print STDERR "ERROR: Unknown option: $arg\n\n" if (!$var);
showUsage();
} elsif ($var eq "copy") {
if($val eq "yes") {

View File

@ -36,6 +36,7 @@ HTML.headerscripts = \
" <script type=\"text/javascript\" src=\"scripts/extras.js\"></script>\n" \
" <script type=\"text/javascript\">\n" \
" \$(function(){\n" \
" \$(\"#footer\").load(\"/style/qt-footer.html\");\n" \
" \$(\"#sidebar-content\").load(\"style/qt5-sidebar.html\");\n" \
" });\n" \
" </script>\n" \

View File

@ -1258,15 +1258,15 @@ li a.active {
color:#404244;
line-height:1.16em
}
.mainContent table p {
margin:0px;
padding:0px
}
.mainContent table p {
margin:0px;
padding:0px;
max-width:initial;
min-height:2em
}
.mainContent table p.centerAlign {
text-align:center
}
.context h2 {
font-size:2.1875em
}

View File

@ -117,7 +117,7 @@ Client::Client(QWidget *parent)
//! [4]
QGridLayout *mainLayout = Q_NULLPTR;
if (QGuiApplication::styleHints()->showIsFullScreen()) {
if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) {
QVBoxLayout *outerVerticalLayout = new QVBoxLayout(this);
outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
QHBoxLayout *outerHorizontalLayout = new QHBoxLayout;

View File

@ -100,7 +100,7 @@ Server::Server(QWidget *parent)
buttonLayout->addStretch(1);
QVBoxLayout *mainLayout = Q_NULLPTR;
if (QGuiApplication::styleHints()->showIsFullScreen()) {
if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) {
QVBoxLayout *outerVerticalLayout = new QVBoxLayout(this);
outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
QHBoxLayout *outerHorizontalLayout = new QHBoxLayout;

View File

@ -98,9 +98,19 @@ int DialogOptionsWidget::value() const
Dialog::Dialog(QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *mainLayout = new QVBoxLayout(this);
QVBoxLayout *verticalLayout;
if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) {
QHBoxLayout *horizontalLayout = new QHBoxLayout(this);
QGroupBox *groupBox = new QGroupBox(QGuiApplication::applicationDisplayName(), this);
horizontalLayout->addWidget(groupBox);
horizontalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
verticalLayout = new QVBoxLayout(groupBox);
} else {
verticalLayout = new QVBoxLayout(this);
}
QToolBox *toolbox = new QToolBox;
mainLayout->addWidget(toolbox);
verticalLayout->addWidget(toolbox);
errorMessageDialog = new QErrorMessage(this);
@ -291,7 +301,7 @@ Dialog::Dialog(QWidget *parent)
layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding), 5, 0);
toolbox->addItem(page, tr("Message Boxes"));
setWindowTitle(tr("Standard Dialogs"));
setWindowTitle(QGuiApplication::applicationDisplayName());
}
void Dialog::setInteger()

View File

@ -39,6 +39,7 @@
****************************************************************************/
#include <QApplication>
#include <QStyleHints>
#include <QDesktopWidget>
#include <QTranslator>
#include <QLocale>
@ -49,6 +50,7 @@
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGuiApplication::setApplicationDisplayName(Dialog::tr("Standard Dialogs"));
#ifndef QT_NO_TRANSLATION
QString translatorFileName = QLatin1String("qt_");
@ -59,10 +61,12 @@ int main(int argc, char *argv[])
#endif
Dialog dialog;
const QRect availableGeometry = QApplication::desktop()->availableGeometry(&dialog);
dialog.resize(availableGeometry.width() / 3, availableGeometry.height() * 2 / 3);
dialog.move((availableGeometry.width() - dialog.width()) / 2,
(availableGeometry.height() - dialog.height()) / 2);
if (!QGuiApplication::styleHints()->showIsFullScreen() && !QGuiApplication::styleHints()->showIsMaximized()) {
const QRect availableGeometry = QApplication::desktop()->availableGeometry(&dialog);
dialog.resize(availableGeometry.width() / 3, availableGeometry.height() * 2 / 3);
dialog.move((availableGeometry.width() - dialog.width()) / 2,
(availableGeometry.height() - dialog.height()) / 2);
}
dialog.show();
return app.exec();

View File

@ -23,3 +23,6 @@ QMAKE_AR = $${CROSS_COMPILE}ar cqs
QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy
QMAKE_NM = $${CROSS_COMPILE}nm -P
QMAKE_STRIP = $${CROSS_COMPILE}strip
contains(DISTRO_OPTS, deb-multi-arch): \
PKG_CONFIG = $${CROSS_COMPILE}pkg-config

View File

@ -0,0 +1,9 @@
#
# Generic qmake configuration for building with g++ on arm devices.
#
# A minimal configure line could look something like this:
# ./configure -device arm-generic-g++ -device-option CROSS_COMPILE=arm-linux-gnueabi-
include(../common/linux_device_pre.conf)
include(../common/linux_arm_device_post.conf)
load(qt_config)

View File

@ -0,0 +1,34 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the qmake spec of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "../../linux-g++/qplatformdefs.h"

View File

@ -90,7 +90,6 @@ load(qt_common)
qmlplugindump = qmlplugindump
importpath.name = QML2_IMPORT_PATH
}
qtPrepareTool(QMLPLUGINDUMP, $$qmlplugindump)
importpath.value =
for(qmod, QTREPOS) {
qml1_target: \
@ -100,7 +99,9 @@ load(qt_common)
exists($$qmod): importpath.value += $$shell_path($$qmod)
}
importpath.value = $$unique(importpath.value)
qtAddToolEnv(QMLPLUGINDUMP, importpath)
QT_TOOL_ENV = importpath
qtPrepareTool(QMLPLUGINDUMP, $$qmlplugindump)
QT_TOOL_ENV =
TARGETPATHBASE = $$replace(TARGETPATH, \\.\\d+\$, )
qmltypes.target = qmltypes
qmltypes.commands = $$QMLPLUGINDUMP -nonrelocatable $$replace(TARGETPATHBASE, /, .) $$IMPORT_VERSION > $$QMLTYPEFILE

View File

@ -55,6 +55,9 @@ QMAKE_DIR_REPLACE_SANE = PRECOMPILED_DIR OBJECTS_DIR MOC_DIR RCC_DIR UI_DIR
cross_compile: \
CONFIG += force_bootstrap
android|ios|winrt: \
CONFIG += builtin_testdata
CONFIG += \
create_prl link_prl \
prepare_docs qt_docs_targets \

View File

@ -18,7 +18,19 @@ QMAKE_DOCS_TARGET = $$replace(QMAKE_DOCS, ^(.*/)?(.*)\\.qdocconf$, \\2)
isEmpty(QMAKE_DOCS_TARGETDIR): QMAKE_DOCS_TARGETDIR = $$QMAKE_DOCS_TARGET
QMAKE_DOCS_OUTPUTDIR = $$QMAKE_DOCS_BASE_OUTDIR/$$QMAKE_DOCS_TARGETDIR
qtver.name = QT_VERSION
qtver.value = $$VERSION
isEmpty(qtver.value): qtver.value = $$MODULE_VERSION
isEmpty(qtver.value): error("No version for documentation specified.")
qtmver.name = QT_VER
qtmver.value = $$replace(qtver.value, ^(\\d+\\.\\d+).*$, \\1)
qtvertag.name = QT_VERSION_TAG
qtvertag.value = $$replace(qtver.value, \.,)
qtdocs.name = QT_INSTALL_DOCS
qtdocs.value = $$[QT_INSTALL_DOCS/src]
QT_TOOL_ENV = qtver qtmver qtvertag qtdocs
qtPrepareTool(QDOC, qdoc)
QT_TOOL_ENV =
QDOC += -outputdir $$QMAKE_DOCS_OUTPUTDIR
!build_online_docs: \
QDOC += -installdir $$[QT_INSTALL_DOCS]
@ -43,17 +55,6 @@ DOC_INDEXES =
PREP_DOC_INDEXES += -indexdir $$[QT_INSTALL_DOCS/get]
DOC_INDEXES += -indexdir $$[QT_INSTALL_DOCS/get]
}
qtver.name = QT_VERSION
qtver.value = $$VERSION
isEmpty(qtver.value): qtver.value = $$MODULE_VERSION
isEmpty(qtver.value): error("No version for documentation specified.")
qtmver.name = QT_VER
qtmver.value = $$replace(qtver.value, ^(\\d+\\.\\d+).*$, \\1)
qtvertag.name = QT_VERSION_TAG
qtvertag.value = $$replace(qtver.value, \.,)
qtdocs.name = QT_INSTALL_DOCS
qtdocs.value = $$[QT_INSTALL_DOCS/src]
qtAddToolEnv(QDOC, qtver qtmver qtvertag qtdocs)
doc_command = $$QDOC $$QMAKE_DOCS
prepare_docs {
prepare_docs.commands += $$doc_command -prepare $$PREP_DOC_INDEXES -no-link-errors

View File

@ -73,3 +73,5 @@ DEFINES *= QT_USE_QSTRINGBUILDER
cache(QT_TOOL.$${MODULE}.$$var, transient)
}
# The variable is re-used by qtPrepareTool(), and we really don't want that.
unset(QT_TOOL_ENV)

View File

@ -79,7 +79,7 @@ isEmpty(BUILDS)|build_pass {
INSTALLS += target
}
contains(INSTALLS, target) {
!builtin_testdata:contains(INSTALLS, target) {
# Install testdata and helpers as well, but only if we're actually installing the test.
#
# Testdata is installed relative to the directory containing the testcase
@ -175,6 +175,20 @@ contains(INSTALLS, target) {
}
}
builtin_testdata {
ALL_TESTDATA = $$TESTDATA $$GENERATED_TESTDATA
# RESOURCES does not support wildcards (for good reasons)
for(td, ALL_TESTDATA): \
testdata.files += $$files($$absolute_path($$td, $$_PRO_FILE_PWD_))
!isEmpty(testdata.files) {
testdata.base = $$_PRO_FILE_PWD_
RESOURCES += testdata
}
!isEmpty(TEST_HELPER_INSTALLS): \
error("This platform does not support tests which require helpers.")
}
macx-xcode:bundle:isEmpty(QMAKE_BUNDLE_EXTENSION) {
QMAKE_PBX_PRODUCT_TYPE = com.apple.product-type.bundle.unit-test
QMAKE_PBX_BUNDLE_TYPE = wrapper.cfbundle

View File

@ -2408,7 +2408,6 @@
\row \li .file \li Specify the subproject \c pro file explicitly. Cannot be
used in conjunction with \c .subdir modifier.
\row \li .depends \li This subproject depends on specified subproject.
Available only on platforms that use makefiles.
\row \li .makefile \li The makefile of subproject.
Available only on platforms that use makefiles.
\row \li .target \li Base string used for makefile targets related to this

View File

@ -388,6 +388,121 @@ QFileInfo QMakeSourceFileInfo::findFileInfo(const QMakeLocalFileName &dep)
return QFileInfo(dep.real());
}
static int skipEscapedLineEnds(const char *buffer, int buffer_len, int offset, int *lines)
{
// Join physical lines to make logical lines, as in the C preprocessor
while (offset + 1 < buffer_len
&& buffer[offset] == '\\'
&& qmake_endOfLine(buffer[offset + 1])) {
offset += 2;
++*lines;
if (offset < buffer_len
&& buffer[offset - 1] == '\r'
&& buffer[offset] == '\n') // CRLF
offset++;
}
return offset;
}
static bool matchWhileUnsplitting(const char *buffer, int buffer_len, int start,
const char *needle, int needle_len,
int *matchlen, int *lines)
{
int x = start;
for (int n = 0; n < needle_len && x < buffer_len;
n++, x = skipEscapedLineEnds(buffer, buffer_len, x + 1, lines)) {
if (buffer[x] != needle[n])
return false;
}
// That also skipped any remaining BSNLs immediately after the match.
// Tell caller how long the match was:
*matchlen = x - start;
return true;
}
/* Advance from an opening quote at buffer[offset] to the matching close quote. */
static int scanPastString(char *buffer, int buffer_len, int offset, int *lines)
{
// It might be a C++11 raw string.
bool israw = false;
if (buffer[offset] == '"' && offset > 0) {
int explore = offset - 1;
while (explore > 0 && buffer[explore] != 'R') {
if (buffer[explore] == '8' || buffer[explore] == 'u' || buffer[explore] == 'U') {
explore--;
} else if (explore > 1 && qmake_endOfLine(buffer[explore])
&& buffer[explore - 1] == '\\') {
explore -= 2;
} else if (explore > 2 && buffer[explore] == '\n'
&& buffer[explore - 1] == '\r'
&& buffer[explore - 2] == '\\') {
explore -= 3;
} else {
break;
}
}
israw = (buffer[explore] == 'R');
}
if (israw) {
#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), lines)
offset = SKIP_BSNL(offset + 1);
const char *const delim = buffer + offset;
int clean = offset;
while (offset < buffer_len && buffer[offset] != '(') {
if (clean < offset)
buffer[clean++] = buffer[offset];
else
clean++;
offset = SKIP_BSNL(offset + 1);
}
/*
Not checking correctness (trust real compiler to do that):
- no controls, spaces, '(', ')', '\\' or (presumably) '"' in delim;
- at most 16 bytes in delim
Raw strings are surely defined after phase 2, when BSNLs are resolved;
so the delimiter's exclusion of '\\' and space (including newlines)
applies too late to save us the need to cope with BSNLs in it.
*/
const int delimlen = buffer + clean - delim;
int matchlen = delimlen, extralines = 0;
while ((offset = SKIP_BSNL(offset + 1)) < buffer_len
&& (buffer[offset] != ')'
|| (delimlen > 0 &&
!matchWhileUnsplitting(buffer, buffer_len,
offset + 1, delim, delimlen,
&matchlen, &extralines))
|| buffer[offset + 1 + matchlen] != '"')) {
// skip, but keep track of lines
if (qmake_endOfLine(buffer[offset]))
++*lines;
extralines = 0;
}
*lines += extralines; // from the match
// buffer[offset] is ')'
offset += 1 + matchlen; // 1 for ')', then delim
// buffer[offset] is '"'
#undef SKIP_BSNL
} else { // Traditional string or char literal:
const char term = buffer[offset];
while (++offset < buffer_len && buffer[offset] != term) {
if (buffer[offset] == '\\')
++offset;
else if (qmake_endOfLine(buffer[offset]))
++*lines;
}
}
return offset;
}
bool QMakeSourceFileInfo::findDeps(SourceFile *file)
{
if(file->dep_checked || file->type == TYPE_UNKNOWN)
@ -426,6 +541,18 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
file->deps = new SourceDependChildren;
int line_count = 1;
enum {
/*
States of C preprocessing (for TYPE_C only), after backslash-newline
elimination and skipping comments and spaces (i.e. in ANSI X3.159-1989
section 2.1.1.2's phase 4). We're about to study buffer[x] to decide
on which transition to do.
*/
AtStart, // start of logical line; a # may start a preprocessor directive
HadHash, // saw a # at start, looking for preprocessor keyword
WantName, // saw #include or #import, waiting for name
InCode // after directive, parsing non-#include directive or in actual code
} cpp_state = AtStart;
for(int x = 0; x < buffer_len; ++x) {
bool try_local = true;
@ -505,118 +632,164 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
++line_count;
} else if(file->type == QMakeSourceFileInfo::TYPE_QRC) {
} else if(file->type == QMakeSourceFileInfo::TYPE_C) {
for(int beginning=1; x < buffer_len; ++x) {
// We've studied all buffer[i] for i < x
for (; x < buffer_len; ++x) {
// How to handle backslash-newline (BSNL) pairs:
#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count)
// Seek code or directive, skipping comments and space:
for(; x < buffer_len; ++x) {
x = SKIP_BSNL(x);
if (buffer[x] == ' ' || buffer[x] == '\t') {
// keep going
} else if (buffer[x] == '/' && x + 1 < buffer_len &&
(buffer[x + 1] == '/' || buffer[x + 1] == '*')) {
++x;
if (buffer[x] == '/') { // C++-style comment
for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip
beginning = 1;
} else { // C-style comment
} else if (buffer[x] == '/') {
int extralines = 0;
int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
if (buffer[y] == '/') { // C++-style comment
line_count += extralines;
x = SKIP_BSNL(y + 1);
while (x < buffer_len && !qmake_endOfLine(buffer[x]))
x = SKIP_BSNL(x + 1); // skip
cpp_state = AtStart;
++line_count;
} else if (buffer[y] == '*') { // C-style comment
line_count += extralines;
x = y;
while (++x < buffer_len) {
x = SKIP_BSNL(x);
if (buffer[x] == '*') {
if (x + 1 < buffer_len && buffer[x + 1] == '/') {
++x; // skip '*'; for loop skips '/'.
extralines = 0;
y = skipEscapedLineEnds(buffer, buffer_len,
x + 1, &extralines);
if (y < buffer_len && buffer[y] == '/') {
line_count += extralines;
x = y; // for loop shall step past this
break;
}
} else if (qmake_endOfLine(buffer[x])) {
++line_count;
}
}
} else {
// buffer[x] is the division operator
break;
}
} else if (qmake_endOfLine(buffer[x])) {
++line_count;
beginning = 1;
cpp_state = AtStart;
} else {
/* Drop out of phases 1, 2, 3, into phase 4 */
break;
}
}
// Phase 4 study of buffer[x]:
if(x >= buffer_len)
break;
// preprocessor directive
if (beginning && buffer[x] == '#') {
// Advance to start of preprocessing directive
while (++x < buffer_len
&& (buffer[x] == ' ' || buffer[x] == '\t')) {} // skip
switch (cpp_state) {
case HadHash:
{
// Read keyword; buffer[x] starts first preprocessing token after #
const char *const keyword = buffer + x;
int clean = x;
while (x < buffer_len && buffer[x] >= 'a' && buffer[x] <= 'z') {
// skip over keyword, consolidating it if it contains BSNLs
// (see WantName's similar code consolidating inc, below)
if (clean < x)
buffer[clean++] = buffer[x];
else
clean++;
if (qmake_endOfLine(buffer[x])) {
++line_count;
beginning = 1;
continue;
x = SKIP_BSNL(x + 1);
}
const int keyword_len = buffer + clean - keyword;
x--; // Still need to study buffer[x] next time round for loop.
cpp_state =
((keyword_len == 7 && !strncmp(keyword, "include", 7)) // C & Obj-C
|| (keyword_len == 6 && !strncmp(keyword, "import", 6))) // Obj-C
? WantName : InCode;
break;
}
// quoted strings
if (buffer[x] == '\'' || buffer[x] == '"') {
const char term = buffer[x];
while (++x < buffer_len) {
if (buffer[x] == term) {
++x;
break;
} else if (buffer[x] == '\\') {
++x;
} else if (qmake_endOfLine(buffer[x])) {
++line_count;
}
case WantName:
{
char term = buffer[x];
if (term == '<') {
try_local = false;
term = '>';
} else if (term != '"') {
/*
Possibly malformed, but this may be something like:
#include IDENTIFIER
which does work, if #define IDENTIFIER "filename" is
in effect. This is beyond this noddy preprocessor's
powers of tracking. So give up and resume searching
for a directive. We haven't made sense of buffer[x],
so back up to ensure we do study it (now as code) next
time round the loop.
*/
x--;
cpp_state = InCode;
continue;
}
x = SKIP_BSNL(x + 1);
inc = buffer + x;
int clean = x; // offset if we need to clear \-newlines
for (; x < buffer_len && buffer[x] != term; x = SKIP_BSNL(x + 1)) {
if (qmake_endOfLine(buffer[x])) { // malformed
cpp_state = AtStart;
++line_count;
break;
}
/*
If we do skip any BSNLs, we need to consolidate the
surviving text by copying to lower indices. For that
to be possible, we also have to keep 'clean' advanced
in step with x even when we've yet to see any BSNLs.
*/
if (clean < x)
buffer[clean++] = buffer[x];
else
clean++;
}
if (cpp_state == WantName)
buffer[clean] = '\0';
else // i.e. malformed
inc = 0;
cpp_state = InCode; // hereafter
break;
}
beginning = 0;
case AtStart:
// Preprocessor directive?
if (buffer[x] == '#') {
cpp_state = HadHash;
break;
}
cpp_state = InCode;
// ... and fall through to handle buffer[x] as such.
case InCode:
// matching quotes (string literals and character literals)
if (buffer[x] == '\'' || buffer[x] == '"') {
x = scanPastString(buffer, buffer_len, x, &line_count);
// for loop's ++x shall step over the closing quote.
}
// else: buffer[x] is just some code; move on.
break;
}
if (inc) // We were in WantName and found a name.
break;
#undef SKIP_BSNL
}
if(x >= buffer_len)
break;
// Got a preprocessor directive
const char *const keyword = buffer + x;
for (;
x < buffer_len && buffer[x] >= 'a' && buffer[x] <= 'z';
x++) {} // skip over identifier
int keyword_len = buffer + x - keyword;
for (;
x < buffer_len && (buffer[x] == ' ' || buffer[x] == '\t');
x++) {} // skip spaces after keyword
/* Keyword with nothing after it, e.g. #endif: not interesting. */
if (qmake_endOfLine(buffer[x]))
keyword_len = 0;
if((keyword_len == 7 && !strncmp(keyword, "include", 7)) // C & Obj-C
|| (keyword_len == 6 && !strncmp(keyword, "import", 6))) { // Obj-C
char term = buffer[x];
if(term == '<') {
try_local = false;
term = '>';
} else if(term != '"') { //wtf?
continue;
}
x++;
inc = buffer + x;
for (;
buffer[x] != term && !qmake_endOfLine(buffer[x]);
++x) {} // skip until end of include name
buffer[x] = '\0';
} else if (buffer[x] == '\'' || buffer[x] == '"') {
const char term = buffer[x++];
while(x < buffer_len) {
if (buffer[x] == term)
break;
if (buffer[x] == '\\') {
x+=2;
} else {
if (qmake_endOfLine(buffer[x]))
++line_count;
++x;
}
}
} else {
--x;
}
}
if(inc) {
@ -699,7 +872,7 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
files_changed = true;
file->moc_checked = true;
int buffer_len;
int buffer_len = 0;
char *buffer = 0;
{
struct stat fst;
@ -717,42 +890,56 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
return false; //shouldn't happen
}
buffer = getBuffer(fst.st_size);
for(int have_read = buffer_len = 0;
(have_read = QT_READ(fd, buffer + buffer_len, fst.st_size - buffer_len));
buffer_len += have_read) ;
while (int have_read = QT_READ(fd, buffer + buffer_len, fst.st_size - buffer_len))
buffer_len += have_read;
QT_CLOSE(fd);
}
debug_msg(2, "findMocs: %s", file->file.local().toLatin1().constData());
int line_count = 1;
bool ignore_qobject = false, ignore_qgadget = false;
bool ignore[2] = { false, false }; // [0] for Q_OBJECT, [1] for Q_GADGET
/* qmake ignore Q_GADGET */
/* qmake ignore Q_OBJECT */
for(int x = 0; x < buffer_len; x++) {
#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count)
x = SKIP_BSNL(x);
if (buffer[x] == '/') {
++x;
if(buffer_len >= x) {
if (buffer[x] == '/') { // C++-style comment
for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip
} else if (buffer[x] == '*') { // C-style comment
for(++x; x < buffer_len; ++x) {
int extralines = 0;
int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
if (buffer_len > y) {
// If comment, advance to the character that ends it:
if (buffer[y] == '/') { // C++-style comment
line_count += extralines;
x = y;
do {
x = SKIP_BSNL(x + 1);
} while (x < buffer_len && !qmake_endOfLine(buffer[x]));
} else if (buffer[y] == '*') { // C-style comment
line_count += extralines;
x = SKIP_BSNL(y + 1);
for (; x < buffer_len; x = SKIP_BSNL(x + 1)) {
if (buffer[x] == 't' || buffer[x] == 'q') { // ignore
if(buffer_len >= (x + 20) &&
!strncmp(buffer + x + 1, "make ignore Q_OBJECT", 20)) {
debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_OBJECT\"",
file->file.real().toLatin1().constData(), line_count);
x += 20;
ignore_qobject = true;
ignore[0] = true;
} else if(buffer_len >= (x + 20) &&
!strncmp(buffer + x + 1, "make ignore Q_GADGET", 20)) {
debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_GADGET\"",
file->file.real().toLatin1().constData(), line_count);
x += 20;
ignore_qgadget = true;
ignore[1] = true;
}
} else if (buffer[x] == '*') {
if (buffer_len >= x + 1 && buffer[x + 1] == '/') {
++x;
extralines = 0;
y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
if (buffer_len > y && buffer[y] == '/') {
line_count += extralines;
x = y;
break;
}
} else if (Option::debug_level && qmake_endOfLine(buffer[x])) {
@ -760,56 +947,44 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
}
}
}
// else: don't update x, buffer[x] is just the division operator.
}
} else if (buffer[x] == '\'' || buffer[x] == '"') {
const char term = buffer[x++];
while(x < buffer_len) {
if (buffer[x] == term)
break;
if (buffer[x] == '\\') {
x+=2;
} else {
if (qmake_endOfLine(buffer[x]))
++line_count;
++x;
}
}
x = scanPastString(buffer, buffer_len, x, &line_count);
// Leaves us on closing quote; for loop's x++ steps us past it.
}
if (Option::debug_level && qmake_endOfLine(buffer[x]))
if (x < buffer_len && Option::debug_level && qmake_endOfLine(buffer[x]))
++line_count;
if (buffer_len > x + 2 && buffer[x + 1] == 'Q' &&
buffer[x + 2] == '_' && !isCWordChar(buffer[x])) {
++x;
int match = 0;
static const char *interesting[] = { "OBJECT", "GADGET" };
for (int interest = 0, m1, m2; interest < 2; ++interest) {
if(interest == 0 && ignore_qobject)
continue;
else if(interest == 1 && ignore_qgadget)
continue;
for (m1 = 0, m2 = 0; interesting[interest][m1]; ++m1) {
if (interesting[interest][m1] != buffer[x + 2 + m1]) {
m2 = -1;
break;
if (buffer_len > x + 8 && !isCWordChar(buffer[x])) {
int morelines = 0;
int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &morelines);
if (buffer[y] == 'Q') {
static const char interesting[][9] = { "Q_OBJECT", "Q_GADGET" };
for (int interest = 0; interest < 2; ++interest) {
if (ignore[interest])
continue;
int matchlen = 0, extralines = 0;
if (matchWhileUnsplitting(buffer, buffer_len, y,
interesting[interest],
strlen(interesting[interest]),
&matchlen, &extralines)
&& y + matchlen < buffer_len
&& !isCWordChar(buffer[y + matchlen])) {
if (Option::debug_level) {
buffer[y + matchlen] = '\0';
debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s",
file->file.real().toLatin1().constData(),
line_count + morelines, buffer + y);
}
file->mocable = true;
return true;
}
++m2;
}
if(m1 == m2) {
match = m2 + 2;
break;
}
}
if (match && !isCWordChar(buffer[x + match])) {
if (Option::debug_level) {
buffer[x + match] = '\0';
debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s",
file->file.real().toLatin1().constData(),
line_count, buffer + x);
}
file->mocable = true;
return true;
}
}
#undef SKIP_BSNL
}
return true;
}

View File

@ -142,18 +142,8 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
const bool isPhone = project->isActiveConfig(QStringLiteral("winphone"));
#ifdef Q_OS_WIN
QString regKeyPrefix;
#if !defined(Q_OS_WIN64) && _WIN32_WINNT >= 0x0501
BOOL isWow64;
IsWow64Process(GetCurrentProcess(), &isWow64);
if (!isWow64)
regKeyPrefix = QStringLiteral("Software\\");
else
#endif
regKeyPrefix = QStringLiteral("Software\\Wow6432Node\\");
QString regKey = regKeyPrefix + QStringLiteral("Microsoft\\VisualStudio\\") + msvcVer + ("\\Setup\\VC\\ProductDir");
const QString vcInstallDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey);
QString regKey = QStringLiteral("Software\\Microsoft\\VisualStudio\\") + msvcVer + ("\\Setup\\VC\\ProductDir");
const QString vcInstallDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey, KEY_WOW64_32KEY);
if (vcInstallDir.isEmpty()) {
fprintf(stderr, "Failed to find the Visual Studio installation directory.\n");
return false;
@ -161,13 +151,13 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
QString windowsPath;
if (isPhone) {
windowsPath = "Microsoft\\Microsoft SDKs\\WindowsPhoneApp\\v";
windowsPath = "Software\\Microsoft\\Microsoft SDKs\\WindowsPhoneApp\\v";
} else {
windowsPath = "Microsoft\\Microsoft SDKs\\Windows\\v";
windowsPath = "Software\\Microsoft\\Microsoft SDKs\\Windows\\v";
}
regKey = regKeyPrefix + windowsPath + winsdkVer + QStringLiteral("\\InstallationFolder");
const QString kitDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey);
regKey = windowsPath + winsdkVer + QStringLiteral("\\InstallationFolder");
const QString kitDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey, KEY_WOW64_32KEY);
if (kitDir.isEmpty()) {
fprintf(stderr, "Failed to find the Windows Kit installation directory.\n");
return false;

View File

@ -70,21 +70,6 @@ struct DotNetCombo {
const char *versionStr;
const char *regKey;
} dotNetCombo[] = {
#ifdef Q_OS_WIN64
{NET2015, "MSVC.NET 2015 (14.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"},
{NET2013, "MSVC.NET 2013 (12.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"},
{NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"},
{NET2012, "MSVC.NET 2012 (11.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\11.0\\Setup\\VC\\ProductDir"},
{NET2012, "MSVC.NET 2012 Express Edition (11.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\11.0\\Setup\\VC\\ProductDir"},
{NET2010, "MSVC.NET 2010 (10.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\10.0\\Setup\\VC\\ProductDir"},
{NET2010, "MSVC.NET 2010 Express Edition (10.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\10.0\\Setup\\VC\\ProductDir"},
{NET2008, "MSVC.NET 2008 (9.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\9.0\\Setup\\VC\\ProductDir"},
{NET2008, "MSVC.NET 2008 Express Edition (9.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\9.0\\Setup\\VC\\ProductDir"},
{NET2005, "MSVC.NET 2005 (8.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"},
{NET2005, "MSVC.NET 2005 Express Edition (8.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\8.0\\Setup\\VC\\ProductDir"},
{NET2003, "MSVC.NET 2003 (7.1)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"},
{NET2002, "MSVC.NET 2002 (7.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"},
#else
{NET2015, "MSVC.NET 2015 (14.0)", "Software\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"},
{NET2013, "MSVC.NET 2013 (12.0)", "Software\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"},
{NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"},
@ -98,7 +83,6 @@ struct DotNetCombo {
{NET2005, "MSVC.NET 2005 Express Edition (8.0)", "Software\\Microsoft\\VCExpress\\8.0\\Setup\\VC\\ProductDir"},
{NET2003, "MSVC.NET 2003 (7.1)", "Software\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"},
{NET2002, "MSVC.NET 2002 (7.0)", "Software\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"},
#endif
{NETUnknown, "", ""},
};
@ -125,7 +109,8 @@ DotNET which_dotnet_version(const QByteArray &preferredVersion = QByteArray())
int installed = 0;
int i = 0;
for(; dotNetCombo[i].version; ++i) {
QString path = qt_readRegistryKey(HKEY_LOCAL_MACHINE, dotNetCombo[i].regKey);
QString path = qt_readRegistryKey(HKEY_LOCAL_MACHINE, dotNetCombo[i].regKey,
KEY_WOW64_32KEY);
if (!path.isEmpty() && installPaths.value(dotNetCombo[i].version) != path) {
lowestInstalledVersion = &dotNetCombo[i];
installPaths.insert(lowestInstalledVersion->version, path);

View File

@ -904,6 +904,7 @@ public class QtActivityDelegate
public void onDestroy()
{
if (m_quitApp) {
QtNative.terminateQt();
if (m_debuggerProcess != null)
m_debuggerProcess.destroy();
System.exit(0);// FIXME remove it or find a better way

View File

@ -294,7 +294,12 @@ public class QtNative
private static void quitApp()
{
m_activity.finish();
runAction(new Runnable() {
@Override
public void run() {
m_activity.finish();
}
});
}
//@ANDROID-9

View File

@ -92,6 +92,7 @@ QT_END_NAMESPACE
#include <private/qthread_p.h>
#include <qfile.h>
#include <qfileinfo.h>
#include <qdir.h>
#include <qlist.h>
#include <qmutex.h>
#include <qsemaphore.h>
@ -362,11 +363,14 @@ void QProcessPrivate::startProcess()
static QBasicMutex cfbundleMutex;
QMutexLocker lock(&cfbundleMutex);
QCFType<CFBundleRef> bundle = CFBundleCreate(0, url);
url = CFBundleCopyExecutableURL(bundle);
// 'executableURL' can be either relative or absolute ...
QCFType<CFURLRef> executableURL = CFBundleCopyExecutableURL(bundle);
// not to depend on caching - make sure it's always absolute.
url = CFURLCopyAbsoluteURL(executableURL);
}
if (url) {
QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
encodedProgramName += "/Contents/MacOS/" + QCFString::toQString(str).toUtf8();
const QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
encodedProgramName += (QDir::separator() + QDir(program).relativeFilePath(QCFString::toQString(str))).toUtf8();
}
}
#endif

View File

@ -693,6 +693,11 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
\internal
*/
/*! \typedef QJsonObject::iterator::pointer
\internal
*/
/*! \fn QJsonObject::iterator::iterator()
Constructs an uninitialized iterator.
@ -895,6 +900,11 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
\internal
*/
/*! \typedef QJsonObject::const_iterator::pointer
\internal
*/
/*! \fn QJsonObject::const_iterator::const_iterator()
Constructs an uninitialized iterator.

View File

@ -104,6 +104,7 @@ public:
typedef int difference_type;
typedef QJsonValue value_type;
typedef QJsonValueRef reference;
typedef QJsonValuePtr pointer;
Q_DECL_CONSTEXPR inline iterator() : o(Q_NULLPTR), i(0) {}
Q_DECL_CONSTEXPR inline iterator(QJsonObject *obj, int index) : o(obj), i(index) {}
@ -146,6 +147,7 @@ public:
typedef int difference_type;
typedef QJsonValue value_type;
typedef QJsonValue reference;
typedef QJsonValuePtr pointer;
Q_DECL_CONSTEXPR inline const_iterator() : o(Q_NULLPTR), i(0) {}
Q_DECL_CONSTEXPR inline const_iterator(const QJsonObject *obj, int index)

View File

@ -201,14 +201,16 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherWinRT);
DWORD waitTime = 0;
do {
// Additional user events have to be handled before timer events, but the function may not
// return yet.
const bool userEventsSent = sendPostedEvents(flags);
emit aboutToBlock();
const QVector<HANDLE> timerHandles = d->timerIdToHandle.values().toVector();
DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, 1, TRUE);
if (waitTime)
emit aboutToBlock();
DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, waitTime, TRUE);
if (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0 + timerHandles.count()) {
const HANDLE handle = timerHandles.value(waitResult - WAIT_OBJECT_0);
ResetEvent(handle);
@ -231,6 +233,13 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
if (userEventsSent)
return true;
// We cannot wait infinitely like on other platforms, as
// WaitForMultipleObjectsEx might not return.
// For instance win32 uses MsgWaitForMultipleObjects to hook
// into the native event loop, while WinRT handles those
// via callbacks.
waitTime = 1;
} while (flags & QEventLoop::WaitForMoreEvents);
return false;
}

View File

@ -58,7 +58,7 @@ void QSharedMemoryPrivate::setErrorString(QLatin1String function)
errorString = QSharedMemory::tr("%1: already exists").arg(function);
break;
case ERROR_FILE_NOT_FOUND:
#ifdef Q_OS_WINCE
#if defined(Q_OS_WINCE) || (defined(Q_OS_WINRT) && _MSC_VER < 1900)
// This happens on CE only if no file is present as CreateFileMappingW
// bails out with this error code
case ERROR_INVALID_PARAMETER:
@ -101,7 +101,11 @@ HANDLE QSharedMemoryPrivate::handle()
Q_UNIMPLEMENTED();
hand = 0;
#elif defined(Q_OS_WINRT)
#if _MSC_VER >= 1900
hand = OpenFileMappingFromApp(FILE_MAP_ALL_ACCESS, FALSE, reinterpret_cast<PCWSTR>(nativeKey.utf16()));
#else
hand = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, (PCWSTR)nativeKey.utf16());
#endif
#elif defined(Q_OS_WINCE)
// This works for opening a mapping too, but always opens it with read/write access in
// attach as it seems.

View File

@ -772,7 +772,7 @@ namespace QtPrivate {
QVariantHash l;
l.reserve(iter.size());
for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
l.insert(it.key().toString(), it.value());
l.insertMulti(it.key().toString(), it.value());
return l;
}
return QVariantValueHelper<QVariantHash>::invoke(v);
@ -788,7 +788,7 @@ namespace QtPrivate {
QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
QVariantMap l;
for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
l.insert(it.key().toString(), it.value());
l.insertMulti(it.key().toString(), it.value());
return l;
}
return QVariantValueHelper<QVariantMap>::invoke(v);

View File

@ -124,7 +124,8 @@ bool QLibraryPrivate::load_sys()
SetErrorMode(oldmode);
#endif
if (!pHnd) {
errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qt_error_string());
errorString = QLibrary::tr("Cannot load library %1: %2").arg(
QDir::toNativeSeparators(fileName)).arg(qt_error_string());
} else {
// Query the actual name of the library that was loaded
errorString.clear();
@ -148,7 +149,8 @@ bool QLibraryPrivate::load_sys()
bool QLibraryPrivate::unload_sys()
{
if (!FreeLibrary(pHnd)) {
errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qt_error_string());
errorString = QLibrary::tr("Cannot unload library %1: %2").arg(
QDir::toNativeSeparators(fileName)).arg(qt_error_string());
return false;
}
errorString.clear();
@ -164,7 +166,8 @@ QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
#endif
if (!address) {
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
QString::fromLatin1(symbol)).arg(fileName).arg(qt_error_string());
QString::fromLatin1(symbol)).arg(
QDir::toNativeSeparators(fileName)).arg(qt_error_string());
} else {
errorString.clear();
}

View File

@ -500,7 +500,7 @@ private:
template <class X>
inline void enableSharedFromThis(const QEnableSharedFromThis<X> *ptr)
{
ptr->initializeFromSharedPointer(*this);
ptr->initializeFromSharedPointer(constCast<typename QtPrivate::remove_cv<T>::type>());
}
inline void enableSharedFromThis(...) {}

View File

@ -1819,6 +1819,17 @@ QString &QString::operator=(const QString &other) Q_DECL_NOTHROW
Assigns the Latin-1 string \a str to this string.
*/
QString &QString::operator=(QLatin1String other)
{
if (isDetached() && other.size() <= capacity()) { // assumes d->alloc == 0 → !isDetached() (sharedNull)
d->size = other.size();
d->data()[other.size()] = 0;
qt_from_latin1(d->data(), other.latin1(), other.size());
} else {
*this = fromLatin1(other.latin1(), other.size());
}
return *this;
}
/*! \fn QString &QString::operator=(const QByteArray &ba)
@ -1869,7 +1880,16 @@ QString &QString::operator=(const QString &other) Q_DECL_NOTHROW
*/
QString &QString::operator=(QChar ch)
{
return operator=(QString(ch));
if (isDetached() && capacity() >= 1) { // assumes d->alloc == 0 → !isDetached() (sharedNull)
// re-use existing capacity:
ushort *dat = d->data();
dat[0] = ch.unicode();
dat[1] = 0;
d->size = 1;
} else {
operator=(QString(ch));
}
return *this;
}
/*!
@ -5667,7 +5687,7 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const
*/
namespace QUnicodeTables {
/*!
/*
\internal
Converts the \a str string starting from the position pointed to by the \a
it iterator, using the Unicode case traits \c Traits, and returns the

View File

@ -221,7 +221,7 @@ public:
inline ~QString();
QString &operator=(QChar c);
QString &operator=(const QString &) Q_DECL_NOTHROW;
inline QString &operator=(QLatin1String latin1);
QString &operator=(QLatin1String latin1);
#ifdef Q_COMPILER_RVALUE_REFS
inline QString(QString && other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); }
inline QString &operator=(QString &&other) Q_DECL_NOTHROW
@ -885,11 +885,6 @@ inline void QString::detach()
{ if (d->ref.isShared() || (d->offset != sizeof(QStringData))) reallocData(uint(d->size) + 1u); }
inline bool QString::isDetached() const
{ return !d->ref.isShared(); }
inline QString &QString::operator=(QLatin1String s)
{
*this = fromLatin1(s.latin1(), s.size());
return *this;
}
inline void QString::clear()
{ if (!isNull()) *this = QString(); }
inline QString::QString(const QString &other) Q_DECL_NOTHROW : d(other.d)

View File

@ -695,6 +695,11 @@ QTimeZone::OffsetData QTimeZone::offsetData(const QDateTime &forDateTime) const
/*!
Returns \c true if the system backend supports obtaining transitions.
Transitions are changes in the time-zone: these happen when DST turns on or
off and when authorities alter the offsets for the time-zone.
\sa nextTransition(), previousTransition(), transitions()
*/
bool QTimeZone::hasTransitions() const

View File

@ -2967,15 +2967,6 @@ static void qInitImageConversions()
#endif
}
class QImageConversionsInitializer {
public:
QImageConversionsInitializer()
{
qInitImageConversions();
}
};
// Ensure initialization if this object file is linked.
static QImageConversionsInitializer qImageConversionsInitializer;
Q_CONSTRUCTOR_FUNCTION(qInitImageConversions);
QT_END_NAMESPACE

View File

@ -104,6 +104,7 @@ public:
};
Q_DECLARE_FLAGS(StandardButtons, StandardButton)
Q_FLAG(StandardButtons)
enum ButtonRole {
// keep this in sync with QDialogButtonBox::ButtonRole and QMessageBox::ButtonRole
@ -128,6 +129,7 @@ public:
Reverse = 0x40000000,
EOL = InvalidRole
};
Q_ENUM(ButtonRole)
enum ButtonLayout {
// keep this in sync with QDialogButtonBox::ButtonLayout and QMessageBox::ButtonLayout
@ -167,6 +169,7 @@ QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QColorDialogOptions
{
Q_GADGET
public:
enum ColorDialogOption {
ShowAlphaChannel = 0x00000001,
@ -175,6 +178,7 @@ public:
};
Q_DECLARE_FLAGS(ColorDialogOptions, ColorDialogOption)
Q_FLAG(ColorDialogOptions)
QColorDialogOptions();
QColorDialogOptions(const QColorDialogOptions &rhs);
@ -226,6 +230,7 @@ private:
class Q_GUI_EXPORT QFontDialogOptions
{
Q_GADGET
public:
enum FontDialogOption {
NoButtons = 0x00000001,
@ -237,6 +242,7 @@ public:
};
Q_DECLARE_FLAGS(FontDialogOptions, FontDialogOption)
Q_FLAG(FontDialogOptions)
QFontDialogOptions();
QFontDialogOptions(const QFontDialogOptions &rhs);
@ -279,11 +285,19 @@ private:
class Q_GUI_EXPORT QFileDialogOptions
{
Q_GADGET
public:
enum ViewMode { Detail, List };
Q_ENUM(ViewMode)
enum FileMode { AnyFile, ExistingFile, Directory, ExistingFiles, DirectoryOnly };
Q_ENUM(FileMode)
enum AcceptMode { AcceptOpen, AcceptSave };
Q_ENUM(AcceptMode)
enum DialogLabel { LookIn, FileName, FileType, Accept, Reject, DialogLabelCount };
Q_ENUM(DialogLabel)
enum FileDialogOption
{
@ -297,6 +311,7 @@ public:
DontUseCustomDirectoryIcons = 0x00000080
};
Q_DECLARE_FLAGS(FileDialogOptions, FileDialogOption)
Q_FLAG(FileDialogOptions)
QFileDialogOptions();
QFileDialogOptions(const QFileDialogOptions &rhs);
@ -396,9 +411,11 @@ private:
class Q_GUI_EXPORT QMessageDialogOptions
{
Q_GADGET
public:
// Keep in sync with QMessageBox::Icon
enum Icon { NoIcon, Information, Warning, Critical, Question };
Q_ENUM(Icon)
QMessageDialogOptions();
QMessageDialogOptions(const QMessageDialogOptions &rhs);

View File

@ -63,6 +63,7 @@ public:
// They could be added as public QAction roles if necessary.
CutRole, CopyRole, PasteRole, SelectAllRole,
RoleCount };
Q_ENUM(MenuRole)
virtual void setTag(quintptr tag) = 0;
virtual quintptr tag()const = 0;
@ -91,6 +92,7 @@ class Q_GUI_EXPORT QPlatformMenu : public QObject
Q_OBJECT
public:
enum MenuType { DefaultMenu = 0, EditMenu };
Q_ENUM(MenuType)
virtual void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) = 0;
virtual void removeMenuItem(QPlatformMenuItem *menuItem) = 0;

View File

@ -57,8 +57,10 @@ public:
Trigger,
MiddleClick
};
Q_ENUM(ActivationReason)
enum MessageIcon { NoIcon, Information, Warning, Critical };
Q_ENUM(MessageIcon)
QPlatformSystemTrayIcon();
~QPlatformSystemTrayIcon();

View File

@ -164,6 +164,8 @@ public:
SmallFont,
MiniFont,
FixedFont,
GroupBoxTitleFont,
TabButtonFont,
NFonts
};

View File

@ -116,8 +116,8 @@ QScreen::~QScreen()
bool movingFromVirtualSibling = primaryScreen && primaryScreen->handle()->virtualSiblings().contains(handle());
// Move any leftover windows to the primary screen
foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
if (window->screen() != this)
foreach (QWindow *window, QGuiApplication::allWindows()) {
if (!window->isTopLevel() || window->screen() != this)
continue;
const bool wasVisible = window->isVisible();

View File

@ -50,6 +50,7 @@
#include <qpa/qplatformwindow.h>
#include <QtCore/private/qobject_p.h>
#include <QtCore/qelapsedtimer.h>
#include <QtGui/QIcon>
QT_BEGIN_NAMESPACE
@ -187,6 +188,7 @@ public:
#endif
bool compositing;
QElapsedTimer lastComposeTime;
};

View File

@ -97,9 +97,11 @@ QOpenGLTexturePrivate::QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarge
break;
case QOpenGLTexture::TargetCubeMap:
bindingTarget = QOpenGLTexture::BindingTargetCubeMap;
faces = 6;
break;
case QOpenGLTexture::TargetCubeMapArray:
bindingTarget = QOpenGLTexture::BindingTargetCubeMapArray;
faces = 6;
break;
case QOpenGLTexture::Target2DMultisample:
bindingTarget = QOpenGLTexture::BindingTarget2DMultisample;
@ -175,7 +177,7 @@ bool QOpenGLTexturePrivate::create()
void QOpenGLTexturePrivate::destroy()
{
if (!context) {
if (!textureId) {
// not created or already destroyed
return;
}

View File

@ -156,7 +156,6 @@ public:
bool autoGenerateMipMaps;
bool storageAllocated;
QPair<int, int> glVersion;
QOpenGLTextureHelper *texFuncs;
QOpenGLTexture::Features features;

View File

@ -32,11 +32,6 @@
****************************************************************************/
#include <qglobal.h>
#ifdef Q_OS_IOS
// We don't build the NEON drawhelpers as they are implemented partly
// in GAS syntax assembly, which is not supported by the iOS toolchain.
#undef __ARM_NEON__
#endif
#include <qstylehints.h>
#include <qguiapplication.h>
@ -6314,8 +6309,13 @@ void qt_memfill32(quint32 *dest, quint32 color, int count)
template<QtPixelOrder> const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *);
#endif
extern void qInitBlendFunctions();
static void qInitDrawhelperFunctions()
{
// Set up basic blend function tables.
qInitBlendFunctions();
#ifdef __SSE2__
qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2;
qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2;
@ -6411,7 +6411,7 @@ static void qInitDrawhelperFunctions()
#endif // SSE2
#if defined(__ARM_NEON__) && !defined(Q_OS_IOS)
#if defined(__ARM_NEON__)
qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
@ -6432,7 +6432,7 @@ static void qInitDrawhelperFunctions()
qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon;
#if !defined(Q_PROCESSOR_ARM_64)
#if defined(ENABLE_PIXMAN_DRAWHELPERS)
// The RGB16 helpers are using Arm32 assemblythat has not been ported to AArch64
qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16_neon;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB16] = qt_blend_rgb16_on_argb32_neon;
@ -6509,19 +6509,7 @@ static void qInitDrawhelperFunctions()
#endif // QT_COMPILER_SUPPORTS_MIPS_DSP || QT_COMPILER_SUPPORTS_MIPS_DSPR2
}
extern void qInitBlendFunctions();
class DrawHelperInitializer {
public:
DrawHelperInitializer()
{
// Set up basic blend function tables.
qInitBlendFunctions();
// Set up architecture optimized methods for the current machine.
qInitDrawhelperFunctions();
}
};
// Ensure initialization if this object file is linked.
static DrawHelperInitializer drawHelperInitializer;
Q_CONSTRUCTOR_FUNCTION(qInitDrawhelperFunctions);
QT_END_NAMESPACE

View File

@ -3653,8 +3653,9 @@ QImage::Format QRasterBuffer::prepare(QImage *image)
drawHelper = qDrawHelper + format;
if (image->depth() == 1 && image->colorTable().size() == 2) {
monoDestinationWithClut = true;
destColor0 = qPremultiply(image->colorTable()[0]);
destColor1 = qPremultiply(image->colorTable()[1]);
const QVector<QRgb> colorTable = image->colorTable();
destColor0 = qPremultiply(colorTable[0]);
destColor1 = qPremultiply(colorTable[1]);
}
return format;

View File

@ -301,6 +301,8 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
return;
}
QWindowPrivate::get(window)->lastComposeTime.start();
QOpenGLFunctions *funcs = context->functions();
funcs->glViewport(0, 0, window->width() * window->devicePixelRatio(), window->height() * window->devicePixelRatio());
funcs->glClearColor(0, 0, 0, translucentBackground ? 0 : 1);

View File

@ -41,7 +41,7 @@
#include "qimage.h"
#include "qbitmap.h"
#include <qdebug.h>
#include <private/qdebug_p.h>
QT_BEGIN_NAMESPACE
@ -422,11 +422,32 @@ QDataStream &operator>>(QDataStream &s, QRegion &r)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug s, const QRegion &r)
{
QVector<QRect> rects = r.rects();
s.nospace() << "QRegion(size=" << rects.size() << "), "
<< "bounds = " << r.boundingRect() << '\n';
for (int i=0; i<rects.size(); ++i)
s << "- " << i << rects.at(i) << '\n';
QDebugStateSaver saver(s);
s.nospace();
s << "QRegion(";
if (r.isNull()) {
s << "null";
} else if (r.isEmpty()) {
s << "empty";
} else {
const QVector<QRect> rects = r.rects();
const int count = rects.size();
if (count > 1)
s << "size=" << count << ", bounds=(";
QtDebugUtils::formatQRect(s, r.boundingRect());
if (count > 1) {
s << ") - [";
for (int i = 0; i < count; ++i) {
if (i)
s << ", ";
s << '(';
QtDebugUtils::formatQRect(s, rects.at(i));
s << ')';
}
s << ']';
}
}
s << ')';
return s;
}
#endif

View File

@ -2110,6 +2110,9 @@ QString QFont::lastResortFamily() const
return QString::fromLatin1("helvetica");
}
extern QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style,
QFont::StyleHint styleHint, QChar::Script script);
/*!
\fn QString QFont::defaultFamily() const
@ -2120,8 +2123,7 @@ QString QFont::lastResortFamily() const
*/
QString QFont::defaultFamily() const
{
QPlatformFontDatabase *fontDB = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
const QStringList fallbacks = fontDB->fallbacksForFamily(QString(), QFont::StyleNormal
const QStringList fallbacks = qt_fallbacksForFamily(QString(), QFont::StyleNormal
, QFont::StyleHint(d->request.styleHint), QChar::Script_Common);
if (!fallbacks.isEmpty())
return fallbacks.first();

View File

@ -47,6 +47,7 @@
#include <qpa/qplatformfontdatabase.h>
#include <qpa/qplatformtheme.h>
#include <QtCore/qcache.h>
#include <QtCore/qmath.h>
#include <stdlib.h>
@ -413,11 +414,45 @@ void QtFontFamily::ensurePopulated()
Q_ASSERT_X(populated, Q_FUNC_INFO, qPrintable(name));
}
struct FallbacksCacheKey {
QString family;
QFont::Style style;
QFont::StyleHint styleHint;
QChar::Script script;
};
inline bool operator==(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) Q_DECL_NOTHROW
{
return lhs.script == rhs.script &&
lhs.styleHint == rhs.styleHint &&
lhs.style == rhs.style &&
lhs.family == rhs.family;
}
inline bool operator!=(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) Q_DECL_NOTHROW
{
return !operator==(lhs, rhs);
}
inline uint qHash(const FallbacksCacheKey &key, uint seed = 0) Q_DECL_NOTHROW
{
QtPrivate::QHashCombine hash;
seed = hash(seed, key.family);
seed = hash(seed, int(key.style));
seed = hash(seed, int(key.styleHint));
seed = hash(seed, int(key.script));
return seed;
}
class QFontDatabasePrivate
{
public:
QFontDatabasePrivate()
: count(0), families(0), reregisterAppFonts(false)
: count(0), families(0),
fallbacksCache(64),
reregisterAppFonts(false)
{ }
~QFontDatabasePrivate() {
@ -443,6 +478,7 @@ public:
int count;
QtFontFamily **families;
QCache<FallbacksCacheKey, QStringList> fallbacksCache;
struct ApplicationFont {
@ -461,6 +497,8 @@ public:
void QFontDatabasePrivate::invalidate()
{
QFontCache::instance()->clear();
fallbacksCache.clear();
free();
QGuiApplicationPrivate::platformIntegration()->fontDatabase()->invalidate();
emit static_cast<QGuiApplication *>(QCoreApplication::instance())->fontDatabaseChanged();
@ -680,8 +718,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fontDatabaseMutex, (QMutex::Recursive))
void qt_cleanupFontDatabase()
{
QFontDatabasePrivate *db = privateDb();
if (db)
if (db) {
db->fallbacksCache.clear();
db->free();
}
}
// used in qfontengine_x11.cpp
@ -800,9 +840,15 @@ QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFo
QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
{
QFontDatabasePrivate *db = privateDb();
const FallbacksCacheKey cacheKey = { family, style, styleHint, script };
if (const QStringList *fallbacks = db->fallbacksCache.object(cacheKey))
return *fallbacks;
// make sure that the db has all fallback families
QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
QFontDatabasePrivate *db = privateDb();
QStringList::iterator i;
for (i = retList.begin(); i != retList.end(); ++i) {
@ -818,6 +864,9 @@ QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFo
--i;
}
}
db->fallbacksCache.insert(cacheKey, new QStringList(retList));
return retList;
}

View File

@ -148,6 +148,9 @@ static void qt_qdnsservicerecord_sort(QList<QDnsServiceRecord> &records)
}
}
const char *QDnsLookupPrivate::msgNoIpV6NameServerAdresses =
QT_TRANSLATE_NOOP("QDnsLookupRunnable", "IPv6 addresses for nameservers are currently not supported");
/*!
\class QDnsLookup
\brief The QDnsLookup class represents a DNS lookup.

View File

@ -89,6 +89,8 @@ public:
void _q_lookupFinished(const QDnsLookupReply &reply);
static const char *msgNoIpV6NameServerAdresses;
bool isFinished;
QString name;
QDnsLookup::Type type;

View File

@ -168,9 +168,9 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
ns->sin6_addr.s6_addr[i] = ipv6Address[i];
}
#else
qWarning("IPv6 addresses for nameservers is currently not supported");
qWarning("%s", QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
reply->error = QDnsLookup::ResolverError;
reply->errorString = tr("IPv6 addresses for nameservers is currently not supported");
reply->errorString = tr(QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
return;
#endif
}

View File

@ -60,9 +60,9 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
// For supoprting IPv6 nameserver addresses, we'll need to switch
// from DnsQuey() to DnsQueryEx() as it supports passing an IPv6
// address in the nameserver list
qWarning("IPv6 addresses for nameservers are currently not supported");
qWarning("%s", QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
reply->error = QDnsLookup::ResolverError;
reply->errorString = tr("IPv6 addresses for nameservers are currently not supported");
reply->errorString = tr(QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
return;
}
}

View File

@ -360,10 +360,15 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
{
QList<QNetworkInterfacePrivate *> interfaces;
QSet<QString> seenInterfaces;
QVarLengthArray<int, 16> seenIndexes; // faster than QSet<int>
// on Linux, AF_PACKET addresses carry the hardware address and interface index;
// scan for them first (they're usually first, but we have no guarantee this
// will be the case forever)
// On Linux, glibc, uClibc and MUSL obtain the address listing via two
// netlink calls: first an RTM_GETLINK to obtain the interface listing,
// then one RTM_GETADDR to get all the addresses (uClibc implementation is
// copied from glibc; Bionic currently doesn't support getifaddrs). They
// synthesize AF_PACKET addresses from the RTM_GETLINK responses, which
// means by construction they currently show up first in the interface
// listing.
for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
if (ptr->ifa_addr && ptr->ifa_addr->sa_family == AF_PACKET) {
sockaddr_ll *sll = (sockaddr_ll *)ptr->ifa_addr;
@ -374,23 +379,30 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
iface->flags = convertFlags(ptr->ifa_flags);
iface->hardwareAddress = iface->makeHwAddress(sll->sll_halen, (uchar*)sll->sll_addr);
Q_ASSERT(!seenIndexes.contains(iface->index));
seenIndexes.append(iface->index);
seenInterfaces.insert(iface->name);
}
}
// see if we missed anything:
// virtual interfaces with no HW address have no AF_PACKET
// - virtual interfaces with no HW address have no AF_PACKET
// - interface labels have no AF_PACKET, but shouldn't be shown as a new interface
for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
if (ptr->ifa_addr && ptr->ifa_addr->sa_family != AF_PACKET) {
QString name = QString::fromLatin1(ptr->ifa_name);
if (seenInterfaces.contains(name))
continue;
int ifindex = if_nametoindex(ptr->ifa_name);
if (seenIndexes.contains(ifindex))
continue;
QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
interfaces << iface;
iface->name = name;
iface->flags = convertFlags(ptr->ifa_flags);
iface->index = if_nametoindex(ptr->ifa_name);
iface->index = ifindex;
}
}
@ -469,7 +481,7 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
interfaces = createInterfaces(interfaceListing);
for (ifaddrs *ptr = interfaceListing; ptr; ptr = ptr->ifa_next) {
// Get the interface index
// Find the interface
QString name = QString::fromLatin1(ptr->ifa_name);
QNetworkInterfacePrivate *iface = 0;
QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
@ -479,6 +491,18 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
iface = *if_it;
break;
}
if (!iface) {
// it may be an interface label, search by interface index
int ifindex = if_nametoindex(ptr->ifa_name);
for (if_it = interfaces.begin(); if_it != interfaces.end(); ++if_it)
if ((*if_it)->index == ifindex) {
// found this interface already
iface = *if_it;
break;
}
}
if (!iface) {
// skip all non-IP interfaces
continue;

View File

@ -96,7 +96,7 @@ public:
qint64 read(char *data, qint64 maxlen);
qint64 write(const char *data, qint64 len);
qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *, PacketHeaderOptions);
qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0, PacketHeaderOptions = WantNone);
qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header);
bool hasPendingDatagrams() const;
qint64 pendingDatagramSize() const;

View File

@ -60,6 +60,15 @@ public:
if (func)
func(window, type);
}
typedef void (*SetHasBorderInFullScreen)(QWindow *window, bool border);
static const QByteArray setHasBorderInFullScreenIdentifier() { return QByteArrayLiteral("WindowsSetHasBorderInFullScreen"); }
static void setHasBorderInFullScreen(QWindow *window, bool border)
{
SetHasBorderInFullScreen func = reinterpret_cast<SetHasBorderInFullScreen>(QGuiApplication::platformFunction(setHasBorderInFullScreenIdentifier()));
if (func)
func(window, border);
}
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QWindowsWindowFunctions::TouchWindowTouchTypes)

View File

@ -69,3 +69,29 @@
This is a convenience function that can be used directly instead of resolving the function pointer.
\a window and \a type will be relayed to the function retrieved by QGuiApplication
*/
/*!
\typedef QWindowsWindowFunctions::SetHasBorderInFullScreen
This is the typedef for the function returned by QGuiApplication::platformFunction when passed setHasBorderInFullScreenIdentifier.
*/
/*!
\fn QByteArray QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier()
\since 5.6
This function returns the bytearray that can be used to query
QGuiApplication::platformFunction to retrieve the SetHasBorderInFullScreen function.
*/
/*!
\fn void QWindowsWindowFunctions::setHasBorderInFullScreen(QWindow *window, bool border)
\since 5.6
This is a convenience function that can be used directly instead of resolving the function pointer.
\a window and \a border will be relayed to the function retrieved by QGuiApplication. When \a border
is true then it will enable the WS_BORDER flag in full screen mode to enable other top level windows
inside the application to appear on top when required.
See also \l [QtDoc] {Fullscreen OpenGL Based Windows}
*/

View File

@ -35,6 +35,7 @@
#include <QtGui/QWindow>
#include <QtGui/QPainter>
#include <qpa/qplatformbackingstore.h>
#include <private/qwindow_p.h>
#include "qopenglcompositorbackingstore_p.h"
#include "qopenglcompositor_p.h"
@ -198,6 +199,8 @@ void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegi
dstCtx->makeCurrent(dstWin);
QWindowPrivate::get(window)->lastComposeTime.start();
m_textures->clear();
for (int i = 0; i < textures->count(); ++i)
m_textures->appendTexture(textures->source(i), textures->textureId(i), textures->geometry(i),

View File

@ -263,11 +263,11 @@ QString TableGenerator::findComposeFile()
{
// check if XCOMPOSEFILE points to a Compose file
if (qEnvironmentVariableIsSet("XCOMPOSEFILE")) {
QString path(qgetenv("XCOMPOSEFILE"));
if (path.endsWith(QLatin1String("Compose")))
const QString path = QFile::decodeName(qgetenv("XCOMPOSEFILE"));
if (QFile::exists(path))
return path;
else
qWarning("Qt Warning: XCOMPOSEFILE doesn't point to a valid Compose file");
qWarning("$XCOMPOSEFILE doesn't point to an existing file");
}
// check if users home directory has a file named .XCompose

View File

@ -34,6 +34,7 @@
#include <dlfcn.h>
#include <pthread.h>
#include <semaphore.h>
#include <qplugin.h>
#include <qdebug.h>
@ -91,6 +92,8 @@ extern "C" typedef int (*Main)(int, char **); //use the standard main method to
static Main m_main = nullptr;
static void *m_mainLibraryHnd = nullptr;
static QList<QByteArray> m_applicationParams;
pthread_t m_qtAppThread = 0;
static sem_t m_exitSemaphore, m_terminateSemaphore;
struct SurfaceData
{
@ -454,6 +457,10 @@ static void *startMainMethod(void */*data*/)
if (vm != 0)
vm->DetachCurrentThread();
sem_post(&m_terminateSemaphore);
sem_wait(&m_exitSemaphore);
sem_destroy(&m_exitSemaphore);
// We must call exit() to ensure that all global objects will be destructed
exit(ret);
return 0;
@ -503,8 +510,13 @@ static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring para
return false;
}
pthread_t appThread;
return pthread_create(&appThread, nullptr, startMainMethod, nullptr) == 0;
if (sem_init(&m_exitSemaphore, 0, 0) == -1)
return false;
if (sem_init(&m_terminateSemaphore, 0, 0) == -1)
return false;
return pthread_create(&m_qtAppThread, nullptr, startMainMethod, nullptr) == 0;
}
@ -518,6 +530,8 @@ static void quitQtAndroidPlugin(JNIEnv *env, jclass /*clazz*/)
static void terminateQt(JNIEnv *env, jclass /*clazz*/)
{
sem_wait(&m_terminateSemaphore);
sem_destroy(&m_terminateSemaphore);
env->DeleteGlobalRef(m_applicationClass);
env->DeleteGlobalRef(m_classLoaderObject);
if (m_resourcesObj)
@ -535,6 +549,8 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/)
m_androidPlatformIntegration = nullptr;
delete m_androidAssetsFileEngineHandler;
m_androidAssetsFileEngineHandler = nullptr;
sem_post(&m_exitSemaphore);
pthread_join(m_qtAppThread, nullptr);
}
static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface, jint w, jint h)

View File

@ -74,7 +74,7 @@ QStringList QAndroidPlatformFontDatabase::fallbacksForFamily(const QString &fami
result.append(QString(qgetenv("QT_ANDROID_FONTS_SERIF")).split(QLatin1Char(';')));
else
result.append(QString(qgetenv("QT_ANDROID_FONTS")).split(QLatin1Char(';')));
result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script));
result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script));
return result;
}

View File

@ -502,7 +502,11 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
QMacAutoReleasePool pool;
if (m_contentViewIsEmbedded) {
QPlatformWindow::setGeometry(rect);
if (m_qtView) {
[m_qtView setFrame:NSMakeRect(0, 0, rect.width(), rect.height())];
} else {
QPlatformWindow::setGeometry(rect);
}
return;
}

View File

@ -45,12 +45,15 @@
QIOSContext::QIOSContext(QOpenGLContext *context)
: QPlatformOpenGLContext()
, m_sharedContext(static_cast<QIOSContext *>(context->shareHandle()))
, m_eaglContext(0)
, m_format(context->format())
{
m_format.setRenderableType(QSurfaceFormat::OpenGLES);
m_eaglContext = [[EAGLContext alloc]
initWithAPI:EAGLRenderingAPI(m_format.majorVersion())
sharegroup:m_sharedContext ? [m_sharedContext->m_eaglContext sharegroup] : nil];
EAGLSharegroup *shareGroup = m_sharedContext ? [m_sharedContext->m_eaglContext sharegroup] : nil;
const int preferredVersion = m_format.majorVersion() == 1 ? kEAGLRenderingAPIOpenGLES1 : kEAGLRenderingAPIOpenGLES3;
for (int version = preferredVersion; !m_eaglContext && version >= m_format.majorVersion(); --version)
m_eaglContext = [[EAGLContext alloc] initWithAPI:EAGLRenderingAPI(version) sharegroup:shareGroup];
if (m_eaglContext != nil) {
EAGLContext *originalContext = [EAGLContext currentContext];

View File

@ -62,11 +62,23 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
{
if (self = [super init]) {
[self setVisibleMenuItems:visibleMenuItems];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(menuClosed)
name:UIMenuControllerDidHideMenuNotification object:nil];
}
return self;
}
-(void)dealloc
{
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:UIMenuControllerDidHideMenuNotification object:nil];
[super dealloc];
}
- (void)setVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems
{
m_visibleMenuItems = visibleMenuItems;
@ -86,6 +98,11 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
[[UIMenuController sharedMenuController] setMenuVisible:YES animated:NO];
}
-(void)menuClosed
{
QIOSMenu::currentMenu()->dismiss();
}
- (id)targetForAction:(SEL)action withSender:(id)sender
{
Q_UNUSED(sender);

View File

@ -318,7 +318,11 @@
// a regular responder transfer to another window. In the former case, iOS
// will set the new first-responder to our next-responder, and in the latter
// case we'll have an active responder candidate.
if ([UIResponder currentFirstResponder] == [self nextResponder]) {
if (![UIResponder currentFirstResponder]) {
// No first responder set anymore, sync this with Qt by clearing the
// focus object.
m_inputContext->clearCurrentFocusObject();
} else if ([UIResponder currentFirstResponder] == [self nextResponder]) {
// We have resigned the keyboard, and transferred first responder back to the parent view
Q_ASSERT(!FirstResponderCandidate::currentCandidate());
if ([self currentImeState:Qt::ImEnabled].toBool()) {
@ -364,6 +368,32 @@
[self sendKeyPressRelease:key modifiers:modifiers];
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
bool isEditAction = (action == @selector(cut:)
|| action == @selector(copy:)
|| action == @selector(paste:)
|| action == @selector(delete:)
|| action == @selector(toggleBoldface:)
|| action == @selector(toggleItalics:)
|| action == @selector(toggleUnderline:)
|| action == @selector(undo)
|| action == @selector(redo));
bool isSelectAction = (action == @selector(select:)
|| action == @selector(selectAll:)
|| action == @selector(paste:)
|| action == @selector(undo)
|| action == @selector(redo));
const bool unknownAction = !isEditAction && !isSelectAction;
const bool hasSelection = ![self selectedTextRange].empty;
if (unknownAction)
return [super canPerformAction:action withSender:sender];
return (hasSelection && isEditAction) || (!hasSelection && isSelectAction);
}
- (void)cut:(id)sender
{
Q_UNUSED(sender);
@ -382,6 +412,13 @@
[self sendShortcut:QKeySequence::Paste];
}
- (void)select:(id)sender
{
Q_UNUSED(sender);
[self sendShortcut:QKeySequence::MoveToPreviousWord];
[self sendShortcut:QKeySequence::SelectNextWord];
}
- (void)selectAll:(id)sender
{
Q_UNUSED(sender);
@ -580,7 +617,8 @@
- (UITextPosition *)endOfDocument
{
int endPosition = [self currentImeState:Qt::ImSurroundingText].toString().length();
QString surroundingText = [self currentImeState:Qt::ImSurroundingText].toString();
int endPosition = surroundingText.length() + m_markedText.length();
return [QUITextPosition positionWithIndex:endPosition];
}
@ -611,9 +649,18 @@
- (NSString *)textInRange:(UITextRange *)range
{
QString text = [self currentImeState:Qt::ImSurroundingText].toString();
if (!m_markedText.isEmpty()) {
// [UITextInput textInRange] is sparsely documented, but it turns out that unconfirmed
// marked text should be seen as a part of the text document. This is different from
// ImSurroundingText, which excludes it.
int cursorPos = [self currentImeState:Qt::ImCursorPosition].toInt();
text = text.left(cursorPos) + m_markedText + text.mid(cursorPos);
}
int s = static_cast<QUITextPosition *>([range start]).index;
int e = static_cast<QUITextPosition *>([range end]).index;
return [self currentImeState:Qt::ImSurroundingText].toString().mid(s, e - s).toNSString();
return text.mid(s, e - s).toNSString();
}
- (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange
@ -882,6 +929,14 @@
if ([text isEqualToString:@"\n"]) {
[self sendKeyPressRelease:Qt::Key_Return modifiers:Qt::NoModifier];
// An onEnter handler of a TextInput might move to the next input by calling
// nextInput.forceActiveFocus() which changes the focusObject.
// In that case we don't want to hide the VKB.
if (focusObject != QGuiApplication::focusObject()) {
qImDebug() << "focusObject already changed, not resigning first responder.";
return;
}
if (self.returnKeyType == UIReturnKeyDone || self.returnKeyType == UIReturnKeyGo
|| self.returnKeyType == UIReturnKeySend || self.returnKeyType == UIReturnKeySearch)
[self resignFirstResponder];

View File

@ -96,7 +96,12 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion &region,
RECT dirty = {dirtyRect.x(), dirtyRect.y(),
dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()};
UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, &ptDst, &size, m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA, &dirty};
QWindowsContext::user32dll.updateLayeredWindowIndirect(rw->handle(), &info);
const BOOL result = QWindowsContext::user32dll.updateLayeredWindowIndirect(rw->handle(), &info);
if (!result)
qErrnoWarning("UpdateLayeredWindowIndirect failed for ptDst=(%d, %d),"
" size=(%dx%d), dirty=(%dx%d %d, %d)", r.x(), r.y(),
r.width(), r.height(), dirtyRect.width(), dirtyRect.height(),
dirtyRect.x(), dirtyRect.y());
} else {
QWindowsContext::user32dll.updateLayeredWindow(rw->handle(), NULL, &ptDst, &size, m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA);
}

View File

@ -192,7 +192,14 @@ typedef struct {
quint16 stringOffset;
} NAME_RECORD;
static QString fontNameFromTTFile(const QString &filename)
typedef struct {
quint32 tag;
quint16 majorVersion;
quint16 minorVersion;
quint32 numFonts;
} TTC_TABLE_HEADER;
static QString fontNameFromTTFile(const QString &filename, int startPos = 0)
{
QFile f(filename);
QString retVal;
@ -200,6 +207,7 @@ static QString fontNameFromTTFile(const QString &filename)
qint64 bytesToRead;
if (f.open(QIODevice::ReadOnly)) {
f.seek(startPos);
OFFSET_TABLE ttOffsetTable;
bytesToRead = sizeof(OFFSET_TABLE);
bytesRead = f.read((char*)&ttOffsetTable, bytesToRead);
@ -280,6 +288,37 @@ static QString fontNameFromTTFile(const QString &filename)
return retVal;
}
static QStringList fontNamesFromTTCFile(const QString &filename)
{
QFile f(filename);
QStringList retVal;
qint64 bytesRead;
qint64 bytesToRead;
if (f.open(QIODevice::ReadOnly)) {
TTC_TABLE_HEADER ttcTableHeader;
bytesToRead = sizeof(TTC_TABLE_HEADER);
bytesRead = f.read((char*)&ttcTableHeader, bytesToRead);
if (bytesToRead != bytesRead)
return retVal;
ttcTableHeader.majorVersion = qFromBigEndian(ttcTableHeader.majorVersion);
ttcTableHeader.minorVersion = qFromBigEndian(ttcTableHeader.minorVersion);
ttcTableHeader.numFonts = qFromBigEndian(ttcTableHeader.numFonts);
if (ttcTableHeader.majorVersion < 1 || ttcTableHeader.majorVersion > 2)
return retVal;
QVarLengthArray<quint32> offsetTable(ttcTableHeader.numFonts);
bytesToRead = sizeof(offsetTable) * ttcTableHeader.numFonts;
bytesRead = f.read((char*)offsetTable.data(), bytesToRead);
if (bytesToRead != bytesRead)
return retVal;
f.close();
for (int i = 0; i < (int)ttcTableHeader.numFonts; ++i)
retVal << fontNameFromTTFile(filename, qFromBigEndian(offsetTable[i]));
}
return retVal;
}
static inline QString fontSettingsOrganization() { return QStringLiteral("Qt-Project"); }
static inline QString fontSettingsApplication() { return QStringLiteral("Qtbase"); }
static inline QString fontSettingsGroup() { return QStringLiteral("CEFontCache"); }
@ -306,20 +345,28 @@ static QString findFontFile(const QString &faceName)
//empty the cache first, as it seems that it is dirty
settings.remove(QString());
QDirIterator it(QStringLiteral("/Windows"), QStringList(QStringLiteral("*.ttf")), QDir::Files | QDir::Hidden | QDir::System);
QDirIterator it(QStringLiteral("/Windows"), QStringList() << QStringLiteral("*.ttf") << QStringLiteral("*.ttc"), QDir::Files | QDir::Hidden | QDir::System);
const QLatin1Char lowerF('f');
const QLatin1Char upperF('F');
while (it.hasNext()) {
const QString fontFile = it.next();
const QString fontName = fontNameFromTTFile(fontFile);
if (fontName.isEmpty())
continue;
fontCache.insert(fontName, fontFile);
settings.setValue(fontName, fontFile);
QStringList fontNames;
const QChar c = fontFile[fontFile.size() - 1];
if (c == lowerF || c == upperF)
fontNames << fontNameFromTTFile(fontFile);
else
fontNames << fontNamesFromTTCFile(fontFile);
foreach (const QString fontName, fontNames) {
if (fontName.isEmpty())
continue;
fontCache.insert(fontName, fontFile);
settings.setValue(fontName, fontFile);
if (localizedName(fontName)) {
QString englishFontName = getEnglishName(fontName);
fontCache.insert(englishFontName, fontFile);
settings.setValue(englishFontName, fontFile);
if (localizedName(fontName)) {
QString englishFontName = getEnglishName(fontName);
fontCache.insert(englishFontName, fontFile);
settings.setValue(englishFontName, fontFile);
}
}
}
settings.endGroup();
@ -675,7 +722,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF
result.append(QWindowsFontDatabase::extraTryFontsForFamily(family));
result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script));
result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script));
qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
<< script << result;

View File

@ -485,9 +485,9 @@ qreal QWindowsFontEngineDirectWrite::maxCharWidth() const
return 0;
}
QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)
QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)
{
QImage im = imageForGlyph(glyph, subPixelPosition, 0, QTransform());
QImage im = alphaRGBMapForGlyph(glyph, subPixelPosition, t);
QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8);
@ -504,6 +504,11 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed sub
return alphaMap;
}
QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)
{
return alphaMapForGlyph(glyph, subPixelPosition, QTransform());
}
bool QWindowsFontEngineDirectWrite::supportsSubPixelPositions() const
{
return true;
@ -709,9 +714,9 @@ QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyN
glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed pos, const QTransform &matrix, GlyphFormat format)
{
Q_UNUSED(pos);
int margin = 0;
if (format == QFontEngine::Format_A32 || format == QFontEngine::Format_ARGB)
margin = glyphMargin(QFontEngine::Format_A32);
Q_UNUSED(format);
int margin = glyphMargin(QFontEngine::Format_A32);
glyph_metrics_t gm = QFontEngine::boundingBox(glyph, matrix);
gm.width += margin * 2;
gm.height += margin * 2;

View File

@ -86,6 +86,7 @@ public:
bool supportsSubPixelPositions() const;
QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition);
QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t);
QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform);
QFontEngine *cloneWithSize(qreal pixelSize) const;

View File

@ -86,10 +86,15 @@ QT_BEGIN_NAMESPACE
The code originates from \c qkeymapper_win.cpp.
*/
static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state);
QWindowsKeyMapper::QWindowsKeyMapper()
: m_useRTLExtensions(false), m_keyGrabber(0)
{
memset(keyLayout, 0, sizeof(keyLayout));
QGuiApplication *app = static_cast<QGuiApplication *>(QGuiApplication::instance());
QObject::connect(app, &QGuiApplication::applicationStateChanged,
app, clearKeyRecorderOnApplicationInActive);
}
QWindowsKeyMapper::~QWindowsKeyMapper()
@ -144,6 +149,12 @@ struct KeyRecorder
};
static KeyRecorder key_recorder;
static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state)
{
if (state == Qt::ApplicationInactive)
key_recorder.clearKeys();
}
KeyRecord *KeyRecorder::findKey(int code, bool remove)
{
KeyRecord *result = 0;

View File

@ -245,6 +245,8 @@ QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &fun
{
if (function == QWindowsWindowFunctions::setTouchWindowTouchTypeIdentifier())
return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic);
else if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier())
return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic);
return Q_NULLPTR;
}

View File

@ -1720,7 +1720,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
if (!m_savedStyle) {
m_savedStyle = style();
#ifndef Q_OS_WINCE
if (oldState == Qt::WindowMinimized) {
if (oldState == Qt::WindowMinimized || oldState == Qt::WindowMaximized) {
const QRect nf = normalFrameGeometry(m_data.hwnd);
if (nf.isValid())
m_savedFrameGeometry = nf;
@ -1735,6 +1735,8 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
newStyle |= WS_SYSMENU;
if (visible)
newStyle |= WS_VISIBLE;
if (testFlag(HasBorderInFullScreen))
newStyle |= WS_BORDER;
setStyle(newStyle);
// Use geometry of QWindow::screen() within creation or the virtual screen the
// window is in (QTBUG-31166, QTBUG-30724).
@ -1769,7 +1771,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
// preserve maximized state
if (visible) {
setFlag(WithinMaximize);
ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA);
clearFlag(WithinMaximize);
}
m_savedStyle = 0;
@ -2371,4 +2373,19 @@ void QWindowsWindow::aboutToMakeCurrent()
#endif
}
void QWindowsWindow::setHasBorderInFullScreenStatic(QWindow *window, bool border)
{
if (!window->handle())
return;
static_cast<QWindowsWindow *>(window->handle())->setHasBorderInFullScreen(border);
}
void QWindowsWindow::setHasBorderInFullScreen(bool border)
{
if (border)
setFlag(HasBorderInFullScreen);
else
clearFlag(HasBorderInFullScreen);
}
QT_END_NAMESPACE

View File

@ -137,7 +137,8 @@ public:
WithinMaximize = 0x40000,
MaximizeToFullScreen = 0x80000,
InputMethodDisabled = 0x100000,
Compositing = 0x200000
Compositing = 0x200000,
HasBorderInFullScreen = 0x400000
};
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
@ -251,7 +252,8 @@ public:
static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes);
void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch);
static void setHasBorderInFullScreenStatic(QWindow *window, bool border);
void setHasBorderInFullScreen(bool border);
private:
inline void show_sys() const;
inline void hide_sys() const;

View File

@ -428,6 +428,21 @@ QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handl
return engine;
}
QStringList QWinRTFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style,
QFont::StyleHint styleHint,
QChar::Script script) const
{
Q_UNUSED(style)
Q_UNUSED(styleHint)
Q_UNUSED(script)
QStringList result;
if (family == QLatin1String("Helvetica"))
result.append(QStringLiteral("Arial"));
result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script));
return result;
}
void QWinRTFontDatabase::releaseHandle(void *handle)
{
if (!handle)

View File

@ -60,6 +60,8 @@ public:
void populateFontDatabase() Q_DECL_OVERRIDE;
void populateFamily(const QString &familyName) Q_DECL_OVERRIDE;
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE;
QStringList fallbacksForFamily(const QString &family, QFont::Style style,
QFont::StyleHint styleHint, QChar::Script script) const Q_DECL_OVERRIDE;
void releaseHandle(void *handle) Q_DECL_OVERRIDE;
private:
QHash<IDWriteFontFile *, FontDescription> m_fonts;

View File

@ -179,42 +179,6 @@ QXcbScreen* QXcbConnection::findScreenForOutput(xcb_window_t rootWindow, xcb_ran
return 0;
}
QXcbScreen* QXcbConnection::createScreen(QXcbVirtualDesktop* virtualDesktop,
xcb_randr_output_t outputId,
xcb_randr_get_output_info_reply_t *output)
{
QString name;
if (output)
name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output),
xcb_randr_get_output_info_name_length(output));
else {
QByteArray displayName = m_displayName;
int dotPos = displayName.lastIndexOf('.');
if (dotPos != -1)
displayName.truncate(dotPos);
name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + QString::number(virtualDesktop->number());
}
return new QXcbScreen(this, virtualDesktop, outputId, output, name);
}
bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output)
{
xcb_generic_error_t *error = 0;
xcb_randr_get_output_primary_cookie_t primaryCookie =
xcb_randr_get_output_primary(xcb_connection(), rootWindow);
QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary (
xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error));
if (!primary || error) {
qWarning("failed to get the primary output of the screen");
free(error);
error = NULL;
}
const bool isPrimary = primary ? (primary->output == output) : false;
return isPrimary;
}
QXcbVirtualDesktop* QXcbConnection::virtualDesktopForRootWindow(xcb_window_t rootWindow)
{
foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops) {
@ -237,8 +201,9 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
// Not for us
return;
qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc;
QXcbScreen *screen = findScreenForCrtc(crtc.window, crtc.crtc);
qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc
<< "mode" << crtc.mode << "relevant screen" << screen;
// Only update geometry when there's a valid mode on the CRTC
// CRTC with node mode could mean that output has been disabled, and we'll
// get RRNotifyOutputChange notification for that.
@ -260,16 +225,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
if (screen && output.connection == XCB_RANDR_CONNECTION_DISCONNECTED) {
qCDebug(lcQpaScreen) << "screen" << screen->name() << "has been disconnected";
// Known screen removed -> delete it
m_screens.removeOne(screen);
virtualDesktop->removeScreen(screen);
QXcbIntegration::instance()->destroyScreen(screen);
// QTBUG-40174, QTBUG-42985: If all screens are removed, wait
// and start rendering again later if a screen becomes available.
destroyScreen(screen);
} else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) {
// New XRandR output is available and it's enabled
if (output.crtc != XCB_NONE && output.mode != XCB_NONE) {
@ -278,59 +234,142 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
screen = createScreen(virtualDesktop, output.output, outputInfo.data());
qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
// Find a fake screen
foreach (QPlatformScreen *scr, virtualDesktop->screens()) {
QXcbScreen *xcbScreen = (QXcbScreen *)scr;
if (xcbScreen->output() == XCB_NONE) {
screen = xcbScreen;
break;
}
}
screen->setPrimary(checkOutputIsPrimary(output.window, output.output));
virtualDesktop->addScreen(screen);
m_screens << screen;
QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
// Windows which had null screens have already had expose events by now.
// They need to be told the screen is back, it's OK to render.
foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle());
if (xcbWin)
xcbWin->maybeSetScreen(screen);
if (screen) {
QString nameWas = screen->name();
// Transform the fake screen into a physical screen
screen->setOutput(output.output, outputInfo.data());
updateScreen(screen, output);
qCDebug(lcQpaScreen) << "output" << screen->name()
<< "is connected and enabled; was fake:" << nameWas;
} else {
screen = createScreen(virtualDesktop, output, outputInfo.data());
qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
}
}
// else ignore disabled screens
} else if (screen) {
// Screen has been disabled -> remove
if (output.crtc == XCB_NONE && output.mode == XCB_NONE) {
// Screen has been disabled
xcb_randr_get_output_info_cookie_t outputInfoCookie =
xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp);
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
if (outputInfo->crtc == XCB_NONE) {
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled";
m_screens.removeOne(screen);
virtualDesktop->removeScreen(screen);
QXcbIntegration::instance()->destroyScreen(screen);
destroyScreen(screen);
} else {
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been temporarily disabled for the mode switch";
// Reset crtc to skip RRCrtcChangeNotify events,
// because they may be invalid in the middle of the mode switch
screen->setCrtc(XCB_NONE);
}
} else {
// Just update existing screen
screen->updateGeometry(output.config_timestamp);
const bool wasPrimary = screen->isPrimary();
screen->setPrimary(checkOutputIsPrimary(output.window, output.output));
if (screen->mode() != output.mode)
screen->updateRefreshRate(output.mode);
// If the screen became primary, reshuffle the order in QGuiApplicationPrivate
if (!wasPrimary && screen->isPrimary()) {
const int idx = m_screens.indexOf(screen);
m_screens.swap(0, idx);
QXcbIntegration::instance()->setPrimaryScreen(screen);
}
updateScreen(screen, output);
qCDebug(lcQpaScreen) << "output has changed" << screen;
}
}
qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
}
}
bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output)
{
xcb_generic_error_t *error = 0;
xcb_randr_get_output_primary_cookie_t primaryCookie =
xcb_randr_get_output_primary(xcb_connection(), rootWindow);
QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary (
xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error));
if (!primary || error) {
qWarning("failed to get the primary output of the screen");
free(error);
error = NULL;
}
const bool isPrimary = primary ? (primary->output == output) : false;
return isPrimary;
}
void QXcbConnection::updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange)
{
screen->setCrtc(outputChange.crtc); // Set the new crtc, because it can be invalid
screen->updateGeometry(outputChange.config_timestamp);
if (screen->mode() != outputChange.mode)
screen->updateRefreshRate(outputChange.mode);
// Only screen which belongs to the primary virtual desktop can be a primary screen
if (screen->screenNumber() == m_primaryScreenNumber) {
if (!screen->isPrimary() && checkOutputIsPrimary(outputChange.window, outputChange.output)) {
screen->setPrimary(true);
// If the screen became primary, reshuffle the order in QGuiApplicationPrivate
const int idx = m_screens.indexOf(screen);
if (idx > 0) {
m_screens.first()->setPrimary(false);
m_screens.swap(0, idx);
}
screen->virtualDesktop()->setPrimaryScreen(screen);
QXcbIntegration::instance()->setPrimaryScreen(screen);
}
}
}
QXcbScreen *QXcbConnection::createScreen(QXcbVirtualDesktop *virtualDesktop,
const xcb_randr_output_change_t &outputChange,
xcb_randr_get_output_info_reply_t *outputInfo)
{
QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputChange.output, outputInfo);
// Only screen which belongs to the primary virtual desktop can be a primary screen
if (screen->screenNumber() == m_primaryScreenNumber)
screen->setPrimary(checkOutputIsPrimary(outputChange.window, outputChange.output));
if (screen->isPrimary()) {
if (!m_screens.isEmpty())
qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
else
qCDebug(lcQpaScreen) << "no outputs";
m_screens.first()->setPrimary(false);
m_screens.prepend(screen);
} else {
m_screens.append(screen);
}
virtualDesktop->addScreen(screen);
QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
return screen;
}
void QXcbConnection::destroyScreen(QXcbScreen *screen)
{
QXcbVirtualDesktop *virtualDesktop = screen->virtualDesktop();
if (virtualDesktop->screens().count() == 1) {
// If there are no other screens on the same virtual desktop,
// then transform the physical screen into a fake screen.
const QString nameWas = screen->name();
screen->setOutput(XCB_NONE, Q_NULLPTR);
qCDebug(lcQpaScreen) << "transformed" << nameWas << "to fake" << screen;
} else {
// There is more than one screen on the same virtual desktop, remove the screen
m_screens.removeOne(screen);
virtualDesktop->removeScreen(screen);
// When primary screen is removed, set the new primary screen
// which belongs to the primary virtual desktop.
if (screen->isPrimary()) {
QXcbScreen *newPrimary = (QXcbScreen *)virtualDesktop->screens().at(0);
newPrimary->setPrimary(true);
const int idx = m_screens.indexOf(newPrimary);
if (idx > 0)
m_screens.swap(0, idx);
QXcbIntegration::instance()->setPrimaryScreen(newPrimary);
}
QXcbIntegration::instance()->destroyScreen(screen);
}
}
@ -338,8 +377,7 @@ void QXcbConnection::initializeScreens()
{
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
int xcbScreenNumber = 0; // screen number in the xcb sense
QXcbScreen* primaryScreen = Q_NULLPTR;
bool hasOutputs = false;
QXcbScreen *primaryScreen = Q_NULLPTR;
while (it.rem) {
// Each "screen" in xcb terminology is a virtual desktop,
// potentially a collection of separate juxtaposed monitors.
@ -348,8 +386,6 @@ void QXcbConnection::initializeScreens()
xcb_screen_t *xcbScreen = it.data;
QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
m_virtualDesktops.append(virtualDesktop);
QList<QPlatformScreen *> siblings;
int outputCount = 0;
if (has_randr_extension) {
xcb_generic_error_t *error = NULL;
// RRGetScreenResourcesCurrent is fast but it may return nothing if the
@ -366,7 +402,7 @@ void QXcbConnection::initializeScreens()
} else {
xcb_timestamp_t timestamp;
xcb_randr_output_t *outputs = Q_NULLPTR;
outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data());
int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data());
if (outputCount) {
timestamp = resources_current->config_timestamp;
outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.data());
@ -393,6 +429,7 @@ void QXcbConnection::initializeScreens()
qWarning("failed to get the primary output of the screen");
free(error);
} else {
QList<QPlatformScreen *> siblings;
for (int i = 0; i < outputCount; i++) {
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output(
xcb_randr_get_output_info_reply(xcb_connection(),
@ -416,9 +453,8 @@ void QXcbConnection::initializeScreens()
continue;
}
QXcbScreen *screen = createScreen(virtualDesktop, outputs[i], output.data());
QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.data());
siblings << screen;
hasOutputs = true;
m_screens << screen;
// There can be multiple outputs per screen, use either
@ -435,11 +471,23 @@ void QXcbConnection::initializeScreens()
}
}
}
virtualDesktop->setScreens(siblings);
}
}
}
}
virtualDesktop->setScreens(siblings);
if (virtualDesktop->screens().isEmpty()) {
// If there are no XRandR outputs or XRandR extension is missing,
// then create a fake/legacy screen.
QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, XCB_NONE, Q_NULLPTR);
qCDebug(lcQpaScreen) << "created fake screen" << screen;
m_screens << screen;
if (m_primaryScreenNumber == xcbScreenNumber) {
primaryScreen = screen;
primaryScreen->setPrimary(true);
}
virtualDesktop->addScreen(screen);
}
xcb_screen_next(&it);
++xcbScreenNumber;
} // for each xcb screen
@ -447,39 +495,25 @@ void QXcbConnection::initializeScreens()
foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops)
virtualDesktop->subscribeToXFixesSelectionNotify();
// If there's no randr extension, or there was some error above, or we found a
// screen which doesn't have outputs for some other reason (e.g. on VNC or ssh -X),
// but the dimensions are known anyway, and we don't already have any lingering
// (possibly disconnected) screens, then showing windows should be possible,
// so create one screen. (QTBUG-31389)
QXcbVirtualDesktop *virtualDesktop = m_virtualDesktops.value(0);
if (virtualDesktop && !hasOutputs && !virtualDesktop->size().isEmpty() && m_screens.isEmpty()) {
QXcbScreen *screen = createScreen(virtualDesktop, 0, Q_NULLPTR);
virtualDesktop->setScreens(QList<QPlatformScreen *>() << screen);
m_screens << screen;
primaryScreen = screen;
primaryScreen->setPrimary(true);
qCDebug(lcQpaScreen) << "found a screen with zero outputs" << screen;
}
// Ensure the primary screen is first in the list
if (primaryScreen) {
Q_ASSERT(!m_screens.isEmpty());
if (m_screens.first() != primaryScreen) {
m_screens.removeOne(primaryScreen);
m_screens.prepend(primaryScreen);
if (m_virtualDesktops.isEmpty()) {
qFatal("QXcbConnection: no screens available");
} else {
// Ensure the primary screen is first on the list
if (primaryScreen) {
if (m_screens.first() != primaryScreen) {
m_screens.removeOne(primaryScreen);
m_screens.prepend(primaryScreen);
}
}
}
// Push the screens to QApplication
QXcbIntegration *integration = QXcbIntegration::instance();
foreach (QXcbScreen* screen, m_screens) {
qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ')';
integration->screenAdded(screen, screen->isPrimary());
}
// Push the screens to QGuiApplication
foreach (QXcbScreen *screen, m_screens) {
qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")";
QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
}
if (!m_screens.isEmpty())
qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
}
}
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName)
@ -553,9 +587,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
initializeXFixes();
initializeScreens();
if (Q_UNLIKELY(m_screens.isEmpty()))
qFatal("QXcbConnection: no screens available");
initializeXRender();
m_xi2Enabled = false;
#if defined(XCB_USE_XINPUT2)

View File

@ -518,15 +518,17 @@ private:
void initializeXShape();
void initializeXKB();
void handleClientMessageEvent(const xcb_client_message_event_t *event);
QXcbScreen* createScreen(QXcbVirtualDesktop *virtualDesktop,
xcb_randr_output_t outputId = XCB_NONE,
xcb_randr_get_output_info_reply_t *output = 0);
QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc);
QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output);
QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow);
bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
void initializeScreens();
void updateScreens(const xcb_randr_notify_event_t *event);
bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
void updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange);
QXcbScreen *createScreen(QXcbVirtualDesktop *virtualDesktop,
const xcb_randr_output_change_t &outputChange,
xcb_randr_get_output_info_reply_t *outputInfo);
void destroyScreen(QXcbScreen *screen);
void initializeScreens();
bool compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const;
bool m_xi2Enabled;

View File

@ -406,6 +406,9 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
#endif // XCB_USE_XINPUT22
case XIValuatorClass: {
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
// Some devices (mice) report a resolution of 0; they will be excluded later,
// for now just prevent a division by zero
const int vciResolution = vci->resolution ? vci->resolution : 1;
if (vci->label == atom(QXcbAtom::AbsMTPositionX))
caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition;
else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor))
@ -414,16 +417,16 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
caps |= QTouchDevice::Pressure;
else if (vci->label == atom(QXcbAtom::RelX)) {
hasRelativeCoords = true;
dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution);
dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
} else if (vci->label == atom(QXcbAtom::RelY)) {
hasRelativeCoords = true;
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
} else if (vci->label == atom(QXcbAtom::AbsX)) {
caps |= QTouchDevice::Position;
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
} else if (vci->label == atom(QXcbAtom::AbsY)) {
caps |= QTouchDevice::Position;
dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution);
dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
}
break;
}

View File

@ -81,6 +81,13 @@ void QXcbVirtualDesktop::addScreen(QPlatformScreen *s)
((QXcbScreen *) s)->isPrimary() ? m_screens.prepend(s) : m_screens.append(s);
}
void QXcbVirtualDesktop::setPrimaryScreen(QPlatformScreen *s)
{
const int idx = m_screens.indexOf(s);
Q_ASSERT(idx > -1);
m_screens.swap(0, idx);
}
QXcbXSettings *QXcbVirtualDesktop::xSettings() const
{
if (!m_xSettings) {
@ -149,16 +156,15 @@ void QXcbVirtualDesktop::updateWorkArea()
}
QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
QString outputName)
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output)
: QXcbObject(connection)
, m_virtualDesktop(virtualDesktop)
, m_output(outputId)
, m_crtc(output ? output->crtc : 0)
, m_crtc(output ? output->crtc : XCB_NONE)
, m_mode(XCB_NONE)
, m_primary(false)
, m_rotation(XCB_RANDR_ROTATION_ROTATE_0)
, m_outputName(outputName)
, m_outputName(getOutputName(output))
, m_outputSizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize())
, m_virtualSize(virtualDesktop->size())
, m_virtualSizeMillimeters(virtualDesktop->physicalSize())
@ -266,6 +272,22 @@ QXcbScreen::~QXcbScreen()
delete m_cursor;
}
QString QXcbScreen::getOutputName(xcb_randr_get_output_info_reply_t *outputInfo)
{
QString name;
if (outputInfo) {
name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(outputInfo),
xcb_randr_get_output_info_name_length(outputInfo));
} else {
QByteArray displayName = connection()->displayName();
int dotPos = displayName.lastIndexOf('.');
if (dotPos != -1)
displayName.truncate(dotPos);
name = QString::fromLocal8Bit(displayName) + QLatin1Char('.')
+ QString::number(m_virtualDesktop->number());
}
return name;
}
QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
{
@ -390,6 +412,16 @@ QPlatformCursor *QXcbScreen::cursor() const
return m_cursor;
}
void QXcbScreen::setOutput(xcb_randr_output_t outputId,
xcb_randr_get_output_info_reply_t *outputInfo)
{
m_output = outputId;
m_crtc = outputInfo ? outputInfo->crtc : XCB_NONE;
m_mode = XCB_NONE;
m_outputName = getOutputName(outputInfo);
// TODO: Send an event to the QScreen instance that the screen changed its name
}
/*!
\brief handle the XCB screen change event and update properties
@ -458,19 +490,10 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan
updateGeometry(change_event->timestamp);
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), m_orientation);
QDpi ldpi = logicalDpi();
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QPlatformScreen::screen(), ldpi.first, ldpi.second);
// Windows which had null screens have already had expose events by now.
// They need to be told the screen is back, it's OK to render.
foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle());
if (xcbWin)
xcbWin->maybeSetScreen(this);
}
}
void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)

View File

@ -72,6 +72,7 @@ public:
void setScreens(QList<QPlatformScreen *> sl) { m_screens = sl; }
void removeScreen(QPlatformScreen *s) { m_screens.removeOne(s); }
void addScreen(QPlatformScreen *s);
void setPrimaryScreen(QPlatformScreen *s);
QXcbXSettings *xSettings() const;
@ -101,10 +102,11 @@ class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen
{
public:
QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
QString outputName);
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *outputInfo);
~QXcbScreen();
QString getOutputName(xcb_randr_get_output_info_reply_t *outputInfo);
QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE;
@ -137,6 +139,10 @@ public:
xcb_randr_crtc_t crtc() const { return m_crtc; }
xcb_randr_mode_t mode() const { return m_mode; }
void setOutput(xcb_randr_output_t outputId,
xcb_randr_get_output_info_reply_t *outputInfo);
void setCrtc(xcb_randr_crtc_t crtc) { m_crtc = crtc; }
void windowShown(QXcbWindow *window);
QString windowManagerName() const { return m_windowManagerName; }
bool syncRequestSupported() const { return m_syncRequestSupported; }

View File

@ -143,7 +143,7 @@ const quint32 XEMBED_VERSION = 0;
QXcbScreen *QXcbWindow::parentScreen()
{
return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : m_xcbScreen;
return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : xcbScreen();
}
// Returns \c true if we should set WM_TRANSIENT_FOR on \a w
@ -266,7 +266,6 @@ static const char *wm_window_type_property_id = "_q_xcb_wm_window_type";
QXcbWindow::QXcbWindow(QWindow *window)
: QPlatformWindow(window)
, m_window(0)
, m_xcbScreen(0)
, m_syncCounter(0)
, m_gravity(XCB_GRAVITY_STATIC)
, m_mapped(false)
@ -322,7 +321,6 @@ void QXcbWindow::create()
QRect rect = windowGeometry();
QXcbScreen *platformScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
m_xcbScreen = platformScreen;
if (type == Qt::Desktop) {
m_window = platformScreen->root();
m_depth = platformScreen->screen()->root_depth;
@ -624,27 +622,18 @@ void QXcbWindow::destroy()
m_pendingSyncRequest->invalidate();
}
void QXcbWindow::maybeSetScreen(QXcbScreen *screen)
{
if (!window()->screen() && screen->geometry().contains(geometry().topLeft())) {
QWindowSystemInterface::handleWindowScreenChanged(window(), static_cast<QPlatformScreen *>(screen)->screen());
QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(0, 0), window()->size())));
}
}
void QXcbWindow::setGeometry(const QRect &rect)
{
QPlatformWindow::setGeometry(rect);
propagateSizeHints();
QXcbScreen *currentScreen = m_xcbScreen;
QXcbScreen *currentScreen = xcbScreen();
QXcbScreen *newScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
if (!newScreen)
newScreen = xcbScreen();
m_xcbScreen = newScreen;
const QRect wmGeometry = windowToWmGeometry(rect);
if (newScreen && newScreen != currentScreen)
@ -848,15 +837,13 @@ void QXcbWindow::hide()
Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window));
// send synthetic UnmapNotify event according to icccm 4.1.4
if (xcbScreen()) {
xcb_unmap_notify_event_t event;
event.response_type = XCB_UNMAP_NOTIFY;
event.event = xcbScreen()->root();
event.window = m_window;
event.from_configure = false;
Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(),
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
}
xcb_unmap_notify_event_t event;
event.response_type = XCB_UNMAP_NOTIFY;
event.event = xcbScreen()->root();
event.window = m_window;
event.from_configure = false;
Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(),
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
xcb_flush(xcb_connection());
@ -1185,8 +1172,6 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
event.data.data32[3] = 0;
event.data.data32[4] = 0;
if (!xcbScreen())
return;
Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
}
@ -1448,8 +1433,6 @@ void QXcbWindow::setParent(const QPlatformWindow *parent)
xcb_parent_id = qXcbParent->xcb_window();
m_embedded = qXcbParent->window()->type() == Qt::ForeignWindow;
} else {
if (!xcbScreen())
return;
xcb_parent_id = xcbScreen()->root();
m_embedded = false;
}
@ -2005,7 +1988,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
{
bool fromSendEvent = (event->response_type & 0x80);
QPoint pos(event->x, event->y);
if (!parent() && !fromSendEvent && xcbScreen()) {
if (!parent() && !fromSendEvent) {
// Do not trust the position, query it instead.
xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(),
xcbScreen()->root(), 0, 0);
@ -2017,21 +2000,38 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
}
}
const QRect rect = QRect(pos, QSize(event->width, event->height));
QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(rect);
// The original geometry requested by setGeometry() might be different
// from what we end up with after applying window constraints.
QRect requestedGeometry = geometry();
QXcbScreen *currentScreen = m_xcbScreen;
m_xcbScreen = static_cast<QXcbScreen*>(newScreen);
const QRect actualGeometry = QRect(pos, QSize(event->width, event->height));
QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(actualGeometry);
if (!newScreen)
return;
QPlatformWindow::setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(window(), rect);
if (newScreen != currentScreen)
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
// Persist the actual geometry so that QWindow::geometry() can
// be queried in the resize event.
QPlatformWindow::setGeometry(actualGeometry);
if (m_mapped)
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
// FIXME: In the case of the requestedGeometry not matching the actualGeometry due
// to e.g. the window manager applying restrictions to the geometry, the application
// will never see a move/resize event if the actualGeometry is the same as the current
// geometry, and may think the requested geometry was fulfilled.
QWindowSystemInterface::handleGeometryChange(window(), actualGeometry);
// QPlatformScreen::screen() is updated asynchronously, so we can't compare it
// with the newScreen. Just send the WindowScreenChanged event and QGuiApplication
// will make the comparison later.
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
// For expose events we have no way of telling QGuiApplication to used the locally
// cached version of the previous state, so we may in some situations end up with
// an additional expose event.
QRect previousGeometry = requestedGeometry != actualGeometry ?
requestedGeometry : qt_window_private(window())->geometry;
if (m_mapped && actualGeometry.size() != previousGeometry.size())
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), actualGeometry.size()));
if (m_usingSyncProtocol && m_syncState == SyncReceived)
m_syncState = SyncAndConfigureReceived;
@ -2298,8 +2298,6 @@ void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
return;
const QPoint local(event->event_x, event->event_y);
if (!xcbScreen())
return;
QPoint global = QPoint(event->root_x, event->root_y);
QWindowSystemInterface::handleEnterEvent(window(), local, global);
}
@ -2317,8 +2315,6 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
if (enterWindow) {
QPoint local(enter->event_x, enter->event_y);
if (!xcbScreen())
return;
QPoint global = QPoint(event->root_x, event->root_y);
QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global);
@ -2334,8 +2330,6 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
connection()->setTime(event->time);
const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
if (!xcbScreen())
return;
if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
if (propertyDeleted)
@ -2655,8 +2649,6 @@ bool QXcbWindow::needsSync() const
void QXcbWindow::postSyncWindowRequest()
{
if (!xcbScreen())
return;
if (!m_pendingSyncRequest) {
QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this);
m_pendingSyncRequest = e;

View File

@ -167,7 +167,6 @@ public:
virtual void create();
virtual void destroy();
void maybeSetScreen(QXcbScreen *screen);
QXcbScreen *screenForNativeGeometry(const QRect &newGeometry) const;
public Q_SLOTS:
@ -215,8 +214,6 @@ protected:
xcb_window_t m_window;
QXcbScreen *m_xcbScreen;
uint m_depth;
QImage::Format m_imageFormat;
bool m_imageRgbSwap;

View File

@ -3795,7 +3795,7 @@ bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) {
Q_Q(QFileDialog);
if (event->matches(QKeySequence::Cancel)) {
q->hide();
q->reject();
return true;
}

View File

@ -198,13 +198,14 @@ QFileInfo QFileSystemModel::fileInfo(const QModelIndex &index) const
bool QFileSystemModel::remove(const QModelIndex &aindex)
{
const QString path = filePath(aindex);
const bool success = QFileInfo(path).isFile() ? QFile::remove(path) : QDir(path).removeRecursively();
#ifndef QT_NO_FILESYSTEMWATCHER
QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
d->fileInfoGatherer.removePath(path);
if (success) {
QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
d->fileInfoGatherer.removePath(path);
}
#endif
if (QFileInfo(path).isFile())
return QFile::remove(path);
return QDir(path).removeRecursively();
return success;
}
/*!
@ -1620,11 +1621,14 @@ bool QFileSystemModel::event(QEvent *event)
bool QFileSystemModel::rmdir(const QModelIndex &aindex)
{
QString path = filePath(aindex);
const bool success = QDir().rmdir(path);
#ifndef QT_NO_FILESYSTEMWATCHER
QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
d->fileInfoGatherer.removePath(path);
if (success) {
QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
d->fileInfoGatherer.removePath(path);
}
#endif
return QDir().rmdir(path);
return success;
}
/*!
@ -1800,10 +1804,6 @@ void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path, const QV
node->fileName = fileName;
}
if (info.size() == -1 && !info.isSymLink()) {
removeNode(parentNode, fileName);
continue;
}
if (*node != info ) {
node->populate(info);
bypassFilters.remove(node);

View File

@ -76,7 +76,7 @@
advises against will produce more easily comprehensible software.
Doing what it tells you to do may also help.
\b{\l{http://www.amazon.com/exec/obidos/ASIN/047159900X/trolltech/t}{The
\b{\l{http://www.amazon.com/New-Windows-Interface-Microsoft-Press/dp/1556156790/}{The
Microsoft Windows User Experience}}, ISBN 1-55615-679-0,
is Microsoft's look and feel bible. Indispensable for everyone who
has customers that worship Microsoft, and it's quite good, too.

View File

@ -1262,7 +1262,7 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
activated when the user clicks or double clicks on it, depending on the
system configuration. It is also activated when the user presses the
activation key (on Windows and X11 this is the \uicontrol Return key, on Mac OS
X it is \uicontrol{Ctrl+0}).
X it is \uicontrol{Command+O}).
*/
/*!

View File

@ -255,7 +255,7 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
\value TextHeuristicRole This action should be put in the application menu based on the action's text
as described in the QMenuBar documentation.
\value ApplicationSpecificRole This action should be put in the application menu with an application specific role
\value AboutQtRole This action matches handles the "About Qt" menu item.
\value AboutQtRole This action handles the "About Qt" menu item.
\value AboutRole This action should be placed where the "About" menu item is in the application menu. The text of
the menu item will be set to "About <application name>". The application name is fetched from the
\c{Info.plist} file in the application's bundle (See \l{Qt for OS X - Deployment}).
@ -1231,7 +1231,7 @@ void QAction::activate(ActionEvent event)
\since 4.2
This indicates what role the action serves in the application menu on Mac
OS X. By default all action have the TextHeuristicRole, which means that
OS X. By default all actions have the TextHeuristicRole, which means that
the action is added based on its text (see QMenuBar for more information).
The menu role can only be changed before the actions are put into the menu

View File

@ -448,6 +448,26 @@ void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTi
if (!widget)
return;
#ifndef QT_NO_OPENGL
// Having every repaint() leading to a sync/flush is bad as it causes
// compositing and waiting for vsync each and every time. Change to
// UpdateLater, except for approx. once per frame to prevent starvation in
// case the control does not get back to the event loop.
QWidget *w = widget->window();
if (updateTime == UpdateNow && w && w->windowHandle() && QWindowPrivate::get(w->windowHandle())->compositing) {
int refresh = 60;
QScreen *ws = w->windowHandle()->screen();
if (ws)
refresh = ws->refreshRate();
QWindowPrivate *wd = QWindowPrivate::get(w->windowHandle());
if (wd->lastComposeTime.isValid()) {
const qint64 elapsed = wd->lastComposeTime.elapsed();
if (elapsed <= qint64(1000.0f / refresh))
updateTime = UpdateLater;
}
}
#endif
switch (updateTime) {
case UpdateLater:
updateRequestSent = true;
@ -621,7 +641,11 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget,
const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint())));
QRect translatedRect = widgetRect;
if (widget != tlw)
translatedRect.translate(widget->mapTo(tlw, QPoint()));
// Graphics effects may exceed window size, clamp.
translatedRect = translatedRect.intersected(QRect(QPoint(), tlw->size()));
if (qt_region_strictContains(dirty, translatedRect)) {
if (updateTime == UpdateNow)
sendUpdateRequest(tlw, updateTime);

View File

@ -1816,7 +1816,8 @@ void QDockAreaLayoutInfo::saveState(QDataStream &stream) const
stream << flags;
if (w->isWindow()) {
stream << w->x() << w->y() << w->width() << w->height();
const QRect geometry = w->geometry();
stream << geometry.x() << geometry.y() << geometry.width() << geometry.height();
} else {
stream << item.pos << item.size << pick(o, item.minimumSize())
<< pick(o, item.maximumSize());

View File

@ -1093,14 +1093,8 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
q->setWindowFlags(flags);
if (!rect.isNull()) {
if (floating) {
q->resize(rect.size());
q->move(rect.topLeft());
} else {
if (!rect.isNull())
q->setGeometry(rect);
}
}
updateButtons();

View File

@ -140,6 +140,8 @@ public:
hr = applicationFactory->CreateInstance(this, &base, &core);
RETURN_VOID_IF_FAILED("Failed to create application container instance");
pidFile = INVALID_HANDLE_VALUE;
}
~AppContainer()
@ -157,6 +159,13 @@ public:
int argc = app->args.count();
char **argv = app->args.data();
const int res = main(argc, argv);
if (app->pidFile != INVALID_HANDLE_VALUE) {
const QByteArray resString = QByteArray::number(res);
WriteFile(app->pidFile, reinterpret_cast<LPCVOID>(resString.constData()),
resString.size(), NULL, NULL);
FlushFileBuffers(app->pidFile);
CloseHandle(app->pidFile);
}
app->core->Exit();
return res;
}, this, CREATE_SUSPENDED, nullptr);
@ -234,6 +243,9 @@ private:
}
}
if (args.count() >= 2 && strncmp(args.at(1), "-ServerName:", 12) == 0)
args.remove(1);
bool develMode = false;
bool debugWait = false;
foreach (const char *arg, args) {
@ -248,11 +260,10 @@ private:
.absoluteFilePath(QString::number(uint(GetCurrentProcessId())) + QStringLiteral(".pid"));
CREATEFILE2_EXTENDED_PARAMETERS params = {
sizeof(CREATEFILE2_EXTENDED_PARAMETERS),
FILE_ATTRIBUTE_NORMAL, FILE_FLAG_DELETE_ON_CLOSE
FILE_ATTRIBUTE_NORMAL
};
// (Unused) handle will automatically be closed when the app exits
CreateFile2(reinterpret_cast<LPCWSTR>(pidFileName.utf16()),
0, FILE_SHARE_READ|FILE_SHARE_DELETE, CREATE_ALWAYS, &params);
pidFile = CreateFile2(reinterpret_cast<LPCWSTR>(pidFileName.utf16()),
GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS, &params);
// Install the develMode message handler
#ifndef Q_OS_WINPHONE
defaultMessageHandler = qInstallMessageHandler(devMessageHandler);
@ -315,6 +326,7 @@ private:
QByteArray commandLine;
QVarLengthArray<char *> args;
HANDLE mainThread;
HANDLE pidFile;
};
// Main entry point for Appx containers

View File

@ -1,6 +1,6 @@
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += \
app \
test
!winrt: SUBDIRS += app
SUBDIRS += test

View File

@ -7,5 +7,5 @@ QT = core testlib
SOURCES = ../tst_qlogging.cpp
DEFINES += QT_MESSAGELOGCONTEXT
TEST_HELPER_INSTALLS = ../app/app
!winrt: TEST_HELPER_INSTALLS = ../app/app
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0

View File

@ -1,2 +1,3 @@
[isWritable:native]
osx-10.10
osx-10.11

View File

@ -2729,7 +2729,7 @@ void tst_QTextStream::readBomSeekBackReadBomAgain()
QFile::remove("utf8bom");
QFile file("utf8bom");
QVERIFY(file.open(QFile::ReadWrite));
file.write("\xef\xbb\xbf" "Andreas");
file.write("\xef\xbb\xbf""Andreas");
file.seek(0);
QCOMPARE(file.pos(), qint64(0));

View File

@ -1,6 +1,6 @@
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += \
signalbug \
test
!winrt: SUBDIRS+= signalbug
SUBDIRS += test

View File

@ -3,5 +3,5 @@ TARGET = ../tst_qobject
QT = core-private network testlib
SOURCES = ../tst_qobject.cpp
TEST_HELPER_INSTALLS = ../signalbug/signalbug
!winrt: TEST_HELPER_INSTALLS = ../signalbug/signalbug
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0

View File

@ -2,6 +2,7 @@
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@ -2516,14 +2517,26 @@ void tst_QVariant::variantMap()
QVariant v = map;
QVariantMap map2 = qvariant_cast<QVariantMap>(v);
QCOMPARE(map2.value("test").toInt(), 42);
QCOMPARE(map2, map);
map2 = v.toMap();
QCOMPARE(map2.value("test").toInt(), 42);
QCOMPARE(map2, map);
QVariant v2 = QVariant(QMetaType::type("QVariantMap"), &map);
QCOMPARE(qvariant_cast<QVariantMap>(v2).value("test").toInt(), 42);
QVariant v3 = QVariant(QMetaType::type("QMap<QString, QVariant>"), &map);
QCOMPARE(qvariant_cast<QVariantMap>(v3).value("test").toInt(), 42);
// multi-keys
map.insertMulti("test", 47);
v = map;
map2 = qvariant_cast<QVariantMap>(v);
QCOMPARE(map2, map);
map2 = v.toMap();
QCOMPARE(map2, map);
}
void tst_QVariant::variantHash()
@ -2533,14 +2546,26 @@ void tst_QVariant::variantHash()
QVariant v = hash;
QVariantHash hash2 = qvariant_cast<QVariantHash>(v);
QCOMPARE(hash2.value("test").toInt(), 42);
QCOMPARE(hash2, hash);
hash2 = v.toHash();
QCOMPARE(hash2.value("test").toInt(), 42);
QCOMPARE(hash2, hash);
QVariant v2 = QVariant(QMetaType::type("QVariantHash"), &hash);
QCOMPARE(qvariant_cast<QVariantHash>(v2).value("test").toInt(), 42);
QVariant v3 = QVariant(QMetaType::type("QHash<QString, QVariant>"), &hash);
QCOMPARE(qvariant_cast<QVariantHash>(v3).value("test").toInt(), 42);
// multi-keys
hash.insertMulti("test", 47);
v = hash;
hash2 = qvariant_cast<QVariantHash>(v);
QCOMPARE(hash2, hash);
hash2 = v.toHash();
QCOMPARE(hash2, hash);
}
class CustomQObject : public QObject {
@ -3258,24 +3283,40 @@ void tst_QVariant::convertIterables() const
map.insert("3", 4);
QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
map.insertMulti("3", 5);
QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
}
{
QVariantMap map;
map.insert("3", 4);
QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
map.insertMulti("3", 5);
QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
}
{
QHash<QString, int> hash;
hash.insert("3", 4);
QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
hash.insertMulti("3", 5);
QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
}
{
QVariantHash hash;
hash.insert("3", 4);
QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
hash.insertMulti("3", 5);
QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
}
}

View File

@ -1,5 +1,7 @@
TEMPLATE = subdirs
SUBDIRS = \
crashonexit \
test
!winrt: SUBDIRS += crashonexit
CONFIG += ordered

View File

@ -5,5 +5,5 @@ CONFIG += console
QT = core testlib
SOURCES = ../tst_qthreadstorage.cpp
TEST_HELPER_INSTALLS = ../crashonexit/crashonexit
!winrt: TEST_HELPER_INSTALLS = ../crashonexit/crashonexit

View File

@ -1,4 +1,4 @@
TEMPLATE = subdirs
SUBDIRS += test \
syslocaleapp
SUBDIRS += test
!winrt: SUBDIRS+=syslocaleapp

View File

@ -17,4 +17,4 @@ win32 {
}
}
TEST_HELPER_INSTALLS = ../syslocaleapp/syslocaleapp
!winrt: TEST_HELPER_INSTALLS = ../syslocaleapp/syslocaleapp

Some files were not shown because too many files have changed in this diff Show More