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"; $var = "version";
$val = shift @ARGV; $val = shift @ARGV;
} elsif($arg =~/^-/) { } elsif($arg =~/^-/) {
print STDERR "Unknown option: $arg\n\n" if (!$var); print STDERR "ERROR: Unknown option: $arg\n\n" if (!$var);
showUsage(); showUsage();
} else { } else {
$basedir = locateSyncProfile($arg); $basedir = locateSyncProfile($arg);
@ -777,7 +777,7 @@ while ( @ARGV ) {
#do something #do something
if(!$var || $var eq "show_help") { 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(); showUsage();
} elsif ($var eq "copy") { } elsif ($var eq "copy") {
if($val eq "yes") { 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\" src=\"scripts/extras.js\"></script>\n" \
" <script type=\"text/javascript\">\n" \ " <script type=\"text/javascript\">\n" \
" \$(function(){\n" \ " \$(function(){\n" \
" \$(\"#footer\").load(\"/style/qt-footer.html\");\n" \
" \$(\"#sidebar-content\").load(\"style/qt5-sidebar.html\");\n" \ " \$(\"#sidebar-content\").load(\"style/qt5-sidebar.html\");\n" \
" });\n" \ " });\n" \
" </script>\n" \ " </script>\n" \

View File

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

View File

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

View File

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

View File

@ -98,9 +98,19 @@ int DialogOptionsWidget::value() const
Dialog::Dialog(QWidget *parent) Dialog::Dialog(QWidget *parent)
: 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; QToolBox *toolbox = new QToolBox;
mainLayout->addWidget(toolbox); verticalLayout->addWidget(toolbox);
errorMessageDialog = new QErrorMessage(this); errorMessageDialog = new QErrorMessage(this);
@ -291,7 +301,7 @@ Dialog::Dialog(QWidget *parent)
layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding), 5, 0); layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding), 5, 0);
toolbox->addItem(page, tr("Message Boxes")); toolbox->addItem(page, tr("Message Boxes"));
setWindowTitle(tr("Standard Dialogs")); setWindowTitle(QGuiApplication::applicationDisplayName());
} }
void Dialog::setInteger() void Dialog::setInteger()

View File

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

View File

@ -23,3 +23,6 @@ QMAKE_AR = $${CROSS_COMPILE}ar cqs
QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy
QMAKE_NM = $${CROSS_COMPILE}nm -P QMAKE_NM = $${CROSS_COMPILE}nm -P
QMAKE_STRIP = $${CROSS_COMPILE}strip 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 qmlplugindump = qmlplugindump
importpath.name = QML2_IMPORT_PATH importpath.name = QML2_IMPORT_PATH
} }
qtPrepareTool(QMLPLUGINDUMP, $$qmlplugindump)
importpath.value = importpath.value =
for(qmod, QTREPOS) { for(qmod, QTREPOS) {
qml1_target: \ qml1_target: \
@ -100,7 +99,9 @@ load(qt_common)
exists($$qmod): importpath.value += $$shell_path($$qmod) exists($$qmod): importpath.value += $$shell_path($$qmod)
} }
importpath.value = $$unique(importpath.value) importpath.value = $$unique(importpath.value)
qtAddToolEnv(QMLPLUGINDUMP, importpath) QT_TOOL_ENV = importpath
qtPrepareTool(QMLPLUGINDUMP, $$qmlplugindump)
QT_TOOL_ENV =
TARGETPATHBASE = $$replace(TARGETPATH, \\.\\d+\$, ) TARGETPATHBASE = $$replace(TARGETPATH, \\.\\d+\$, )
qmltypes.target = qmltypes qmltypes.target = qmltypes
qmltypes.commands = $$QMLPLUGINDUMP -nonrelocatable $$replace(TARGETPATHBASE, /, .) $$IMPORT_VERSION > $$QMLTYPEFILE 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: \ cross_compile: \
CONFIG += force_bootstrap CONFIG += force_bootstrap
android|ios|winrt: \
CONFIG += builtin_testdata
CONFIG += \ CONFIG += \
create_prl link_prl \ create_prl link_prl \
prepare_docs qt_docs_targets \ 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 isEmpty(QMAKE_DOCS_TARGETDIR): QMAKE_DOCS_TARGETDIR = $$QMAKE_DOCS_TARGET
QMAKE_DOCS_OUTPUTDIR = $$QMAKE_DOCS_BASE_OUTDIR/$$QMAKE_DOCS_TARGETDIR 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) qtPrepareTool(QDOC, qdoc)
QT_TOOL_ENV =
QDOC += -outputdir $$QMAKE_DOCS_OUTPUTDIR QDOC += -outputdir $$QMAKE_DOCS_OUTPUTDIR
!build_online_docs: \ !build_online_docs: \
QDOC += -installdir $$[QT_INSTALL_DOCS] QDOC += -installdir $$[QT_INSTALL_DOCS]
@ -43,17 +55,6 @@ DOC_INDEXES =
PREP_DOC_INDEXES += -indexdir $$[QT_INSTALL_DOCS/get] PREP_DOC_INDEXES += -indexdir $$[QT_INSTALL_DOCS/get]
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 doc_command = $$QDOC $$QMAKE_DOCS
prepare_docs { prepare_docs {
prepare_docs.commands += $$doc_command -prepare $$PREP_DOC_INDEXES -no-link-errors 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) 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 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. # 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 # 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) { macx-xcode:bundle:isEmpty(QMAKE_BUNDLE_EXTENSION) {
QMAKE_PBX_PRODUCT_TYPE = com.apple.product-type.bundle.unit-test QMAKE_PBX_PRODUCT_TYPE = com.apple.product-type.bundle.unit-test
QMAKE_PBX_BUNDLE_TYPE = wrapper.cfbundle 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 \row \li .file \li Specify the subproject \c pro file explicitly. Cannot be
used in conjunction with \c .subdir modifier. used in conjunction with \c .subdir modifier.
\row \li .depends \li This subproject depends on specified subproject. \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. \row \li .makefile \li The makefile of subproject.
Available only on platforms that use makefiles. Available only on platforms that use makefiles.
\row \li .target \li Base string used for makefile targets related to this \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()); 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) bool QMakeSourceFileInfo::findDeps(SourceFile *file)
{ {
if(file->dep_checked || file->type == TYPE_UNKNOWN) if(file->dep_checked || file->type == TYPE_UNKNOWN)
@ -426,6 +541,18 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
file->deps = new SourceDependChildren; file->deps = new SourceDependChildren;
int line_count = 1; 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) { for(int x = 0; x < buffer_len; ++x) {
bool try_local = true; bool try_local = true;
@ -505,118 +632,164 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
++line_count; ++line_count;
} else if(file->type == QMakeSourceFileInfo::TYPE_QRC) { } else if(file->type == QMakeSourceFileInfo::TYPE_QRC) {
} else if(file->type == QMakeSourceFileInfo::TYPE_C) { } else if(file->type == QMakeSourceFileInfo::TYPE_C) {
for(int beginning=1; x < buffer_len; ++x) { // 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: // Seek code or directive, skipping comments and space:
for(; x < buffer_len; ++x) { for(; x < buffer_len; ++x) {
x = SKIP_BSNL(x);
if (buffer[x] == ' ' || buffer[x] == '\t') { if (buffer[x] == ' ' || buffer[x] == '\t') {
// keep going // keep going
} else if (buffer[x] == '/' && x + 1 < buffer_len && } else if (buffer[x] == '/') {
(buffer[x + 1] == '/' || buffer[x + 1] == '*')) { int extralines = 0;
++x; int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
if (buffer[x] == '/') { // C++-style comment if (buffer[y] == '/') { // C++-style comment
for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip line_count += extralines;
beginning = 1; x = SKIP_BSNL(y + 1);
} else { // C-style comment 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) { while (++x < buffer_len) {
x = SKIP_BSNL(x);
if (buffer[x] == '*') { if (buffer[x] == '*') {
if (x + 1 < buffer_len && buffer[x + 1] == '/') { extralines = 0;
++x; // skip '*'; for loop skips '/'. 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; break;
} }
} else if (qmake_endOfLine(buffer[x])) { } else if (qmake_endOfLine(buffer[x])) {
++line_count; ++line_count;
} }
} }
} else {
// buffer[x] is the division operator
break;
} }
} else if (qmake_endOfLine(buffer[x])) { } else if (qmake_endOfLine(buffer[x])) {
++line_count; ++line_count;
beginning = 1; cpp_state = AtStart;
} else { } else {
/* Drop out of phases 1, 2, 3, into phase 4 */
break; break;
} }
} }
// Phase 4 study of buffer[x]:
if(x >= buffer_len) if(x >= buffer_len)
break; break;
// preprocessor directive switch (cpp_state) {
if (beginning && buffer[x] == '#') { case HadHash:
// Advance to start of preprocessing directive {
while (++x < buffer_len // Read keyword; buffer[x] starts first preprocessing token after #
&& (buffer[x] == ' ' || buffer[x] == '\t')) {} // skip 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])) { x = SKIP_BSNL(x + 1);
++line_count;
beginning = 1;
continue;
} }
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; break;
} }
// quoted strings case WantName:
if (buffer[x] == '\'' || buffer[x] == '"') { {
const char term = buffer[x]; char term = buffer[x];
while (++x < buffer_len) { if (term == '<') {
if (buffer[x] == term) { try_local = false;
++x; term = '>';
break; } else if (term != '"') {
} else if (buffer[x] == '\\') { /*
++x; Possibly malformed, but this may be something like:
} else if (qmake_endOfLine(buffer[x])) { #include IDENTIFIER
++line_count; 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) if(x >= buffer_len)
break; 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) { if(inc) {
@ -699,7 +872,7 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
files_changed = true; files_changed = true;
file->moc_checked = true; file->moc_checked = true;
int buffer_len; int buffer_len = 0;
char *buffer = 0; char *buffer = 0;
{ {
struct stat fst; struct stat fst;
@ -717,42 +890,56 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
return false; //shouldn't happen return false; //shouldn't happen
} }
buffer = getBuffer(fst.st_size); buffer = getBuffer(fst.st_size);
for(int have_read = buffer_len = 0; while (int have_read = QT_READ(fd, buffer + buffer_len, fst.st_size - buffer_len))
(have_read = QT_READ(fd, buffer + buffer_len, fst.st_size - buffer_len)); buffer_len += have_read;
buffer_len += have_read) ;
QT_CLOSE(fd); QT_CLOSE(fd);
} }
debug_msg(2, "findMocs: %s", file->file.local().toLatin1().constData()); debug_msg(2, "findMocs: %s", file->file.local().toLatin1().constData());
int line_count = 1; 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_GADGET */
/* qmake ignore Q_OBJECT */ /* qmake ignore Q_OBJECT */
for(int x = 0; x < buffer_len; x++) { for(int x = 0; x < buffer_len; x++) {
#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count)
x = SKIP_BSNL(x);
if (buffer[x] == '/') { if (buffer[x] == '/') {
++x; int extralines = 0;
if(buffer_len >= x) { int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
if (buffer[x] == '/') { // C++-style comment if (buffer_len > y) {
for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip // If comment, advance to the character that ends it:
} else if (buffer[x] == '*') { // C-style comment if (buffer[y] == '/') { // C++-style comment
for(++x; x < buffer_len; ++x) { 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[x] == 't' || buffer[x] == 'q') { // ignore
if(buffer_len >= (x + 20) && if(buffer_len >= (x + 20) &&
!strncmp(buffer + x + 1, "make ignore Q_OBJECT", 20)) { !strncmp(buffer + x + 1, "make ignore Q_OBJECT", 20)) {
debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_OBJECT\"", debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_OBJECT\"",
file->file.real().toLatin1().constData(), line_count); file->file.real().toLatin1().constData(), line_count);
x += 20; x += 20;
ignore_qobject = true; ignore[0] = true;
} else if(buffer_len >= (x + 20) && } else if(buffer_len >= (x + 20) &&
!strncmp(buffer + x + 1, "make ignore Q_GADGET", 20)) { !strncmp(buffer + x + 1, "make ignore Q_GADGET", 20)) {
debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_GADGET\"", debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_GADGET\"",
file->file.real().toLatin1().constData(), line_count); file->file.real().toLatin1().constData(), line_count);
x += 20; x += 20;
ignore_qgadget = true; ignore[1] = true;
} }
} else if (buffer[x] == '*') { } else if (buffer[x] == '*') {
if (buffer_len >= x + 1 && buffer[x + 1] == '/') { extralines = 0;
++x; y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
if (buffer_len > y && buffer[y] == '/') {
line_count += extralines;
x = y;
break; break;
} }
} else if (Option::debug_level && qmake_endOfLine(buffer[x])) { } 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] == '"') { } else if (buffer[x] == '\'' || buffer[x] == '"') {
const char term = buffer[x++]; x = scanPastString(buffer, buffer_len, x, &line_count);
while(x < buffer_len) { // Leaves us on closing quote; for loop's x++ steps us past it.
if (buffer[x] == term)
break;
if (buffer[x] == '\\') {
x+=2;
} else {
if (qmake_endOfLine(buffer[x]))
++line_count;
++x;
}
}
} }
if (Option::debug_level && qmake_endOfLine(buffer[x]))
if (x < buffer_len && Option::debug_level && qmake_endOfLine(buffer[x]))
++line_count; ++line_count;
if (buffer_len > x + 2 && buffer[x + 1] == 'Q' && if (buffer_len > x + 8 && !isCWordChar(buffer[x])) {
buffer[x + 2] == '_' && !isCWordChar(buffer[x])) { int morelines = 0;
++x; int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &morelines);
int match = 0; if (buffer[y] == 'Q') {
static const char *interesting[] = { "OBJECT", "GADGET" }; static const char interesting[][9] = { "Q_OBJECT", "Q_GADGET" };
for (int interest = 0, m1, m2; interest < 2; ++interest) { for (int interest = 0; interest < 2; ++interest) {
if(interest == 0 && ignore_qobject) if (ignore[interest])
continue; continue;
else if(interest == 1 && ignore_qgadget)
continue; int matchlen = 0, extralines = 0;
for (m1 = 0, m2 = 0; interesting[interest][m1]; ++m1) { if (matchWhileUnsplitting(buffer, buffer_len, y,
if (interesting[interest][m1] != buffer[x + 2 + m1]) { interesting[interest],
m2 = -1; strlen(interesting[interest]),
break; &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; return true;
} }

View File

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

View File

@ -70,21 +70,6 @@ struct DotNetCombo {
const char *versionStr; const char *versionStr;
const char *regKey; const char *regKey;
} dotNetCombo[] = { } 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"}, {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 (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"}, {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"}, {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"}, {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"}, {NET2002, "MSVC.NET 2002 (7.0)", "Software\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"},
#endif
{NETUnknown, "", ""}, {NETUnknown, "", ""},
}; };
@ -125,7 +109,8 @@ DotNET which_dotnet_version(const QByteArray &preferredVersion = QByteArray())
int installed = 0; int installed = 0;
int i = 0; int i = 0;
for(; dotNetCombo[i].version; ++i) { 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) { if (!path.isEmpty() && installPaths.value(dotNetCombo[i].version) != path) {
lowestInstalledVersion = &dotNetCombo[i]; lowestInstalledVersion = &dotNetCombo[i];
installPaths.insert(lowestInstalledVersion->version, path); installPaths.insert(lowestInstalledVersion->version, path);

View File

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

View File

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

View File

@ -92,6 +92,7 @@ QT_END_NAMESPACE
#include <private/qthread_p.h> #include <private/qthread_p.h>
#include <qfile.h> #include <qfile.h>
#include <qfileinfo.h> #include <qfileinfo.h>
#include <qdir.h>
#include <qlist.h> #include <qlist.h>
#include <qmutex.h> #include <qmutex.h>
#include <qsemaphore.h> #include <qsemaphore.h>
@ -362,11 +363,14 @@ void QProcessPrivate::startProcess()
static QBasicMutex cfbundleMutex; static QBasicMutex cfbundleMutex;
QMutexLocker lock(&cfbundleMutex); QMutexLocker lock(&cfbundleMutex);
QCFType<CFBundleRef> bundle = CFBundleCreate(0, url); 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) { if (url) {
QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); const QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
encodedProgramName += "/Contents/MacOS/" + QCFString::toQString(str).toUtf8(); encodedProgramName += (QDir::separator() + QDir(program).relativeFilePath(QCFString::toQString(str))).toUtf8();
} }
} }
#endif #endif

View File

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

View File

@ -104,6 +104,7 @@ public:
typedef int difference_type; typedef int difference_type;
typedef QJsonValue value_type; typedef QJsonValue value_type;
typedef QJsonValueRef reference; typedef QJsonValueRef reference;
typedef QJsonValuePtr pointer;
Q_DECL_CONSTEXPR inline iterator() : o(Q_NULLPTR), i(0) {} Q_DECL_CONSTEXPR inline iterator() : o(Q_NULLPTR), i(0) {}
Q_DECL_CONSTEXPR inline iterator(QJsonObject *obj, int index) : o(obj), i(index) {} Q_DECL_CONSTEXPR inline iterator(QJsonObject *obj, int index) : o(obj), i(index) {}
@ -146,6 +147,7 @@ public:
typedef int difference_type; typedef int difference_type;
typedef QJsonValue value_type; typedef QJsonValue value_type;
typedef QJsonValue reference; typedef QJsonValue reference;
typedef QJsonValuePtr pointer;
Q_DECL_CONSTEXPR inline const_iterator() : o(Q_NULLPTR), i(0) {} Q_DECL_CONSTEXPR inline const_iterator() : o(Q_NULLPTR), i(0) {}
Q_DECL_CONSTEXPR inline const_iterator(const QJsonObject *obj, int index) 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); Q_D(QEventDispatcherWinRT);
DWORD waitTime = 0;
do { do {
// Additional user events have to be handled before timer events, but the function may not // Additional user events have to be handled before timer events, but the function may not
// return yet. // return yet.
const bool userEventsSent = sendPostedEvents(flags); const bool userEventsSent = sendPostedEvents(flags);
emit aboutToBlock();
const QVector<HANDLE> timerHandles = d->timerIdToHandle.values().toVector(); 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()) { if (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0 + timerHandles.count()) {
const HANDLE handle = timerHandles.value(waitResult - WAIT_OBJECT_0); const HANDLE handle = timerHandles.value(waitResult - WAIT_OBJECT_0);
ResetEvent(handle); ResetEvent(handle);
@ -231,6 +233,13 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
if (userEventsSent) if (userEventsSent)
return true; 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); } while (flags & QEventLoop::WaitForMoreEvents);
return false; return false;
} }

View File

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

View File

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

View File

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

View File

@ -500,7 +500,7 @@ private:
template <class X> template <class X>
inline void enableSharedFromThis(const QEnableSharedFromThis<X> *ptr) inline void enableSharedFromThis(const QEnableSharedFromThis<X> *ptr)
{ {
ptr->initializeFromSharedPointer(*this); ptr->initializeFromSharedPointer(constCast<typename QtPrivate::remove_cv<T>::type>());
} }
inline void enableSharedFromThis(...) {} 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. 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) /*! \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) 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 { namespace QUnicodeTables {
/*! /*
\internal \internal
Converts the \a str string starting from the position pointed to by the \a 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 it iterator, using the Unicode case traits \c Traits, and returns the

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -32,11 +32,6 @@
****************************************************************************/ ****************************************************************************/
#include <qglobal.h> #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 <qstylehints.h>
#include <qguiapplication.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 *); template<QtPixelOrder> const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *);
#endif #endif
extern void qInitBlendFunctions();
static void qInitDrawhelperFunctions() static void qInitDrawhelperFunctions()
{ {
// Set up basic blend function tables.
qInitBlendFunctions();
#ifdef __SSE2__ #ifdef __SSE2__
qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2; qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2;
qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2; qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2;
@ -6411,7 +6411,7 @@ static void qInitDrawhelperFunctions()
#endif // SSE2 #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_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_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; 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; 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 // 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_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; 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 #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. // Ensure initialization if this object file is linked.
static DrawHelperInitializer drawHelperInitializer; Q_CONSTRUCTOR_FUNCTION(qInitDrawhelperFunctions);
QT_END_NAMESPACE QT_END_NAMESPACE

View File

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

View File

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

View File

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

View File

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

View File

@ -47,6 +47,7 @@
#include <qpa/qplatformfontdatabase.h> #include <qpa/qplatformfontdatabase.h>
#include <qpa/qplatformtheme.h> #include <qpa/qplatformtheme.h>
#include <QtCore/qcache.h>
#include <QtCore/qmath.h> #include <QtCore/qmath.h>
#include <stdlib.h> #include <stdlib.h>
@ -413,11 +414,45 @@ void QtFontFamily::ensurePopulated()
Q_ASSERT_X(populated, Q_FUNC_INFO, qPrintable(name)); 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 class QFontDatabasePrivate
{ {
public: public:
QFontDatabasePrivate() QFontDatabasePrivate()
: count(0), families(0), reregisterAppFonts(false) : count(0), families(0),
fallbacksCache(64),
reregisterAppFonts(false)
{ } { }
~QFontDatabasePrivate() { ~QFontDatabasePrivate() {
@ -443,6 +478,7 @@ public:
int count; int count;
QtFontFamily **families; QtFontFamily **families;
QCache<FallbacksCacheKey, QStringList> fallbacksCache;
struct ApplicationFont { struct ApplicationFont {
@ -461,6 +497,8 @@ public:
void QFontDatabasePrivate::invalidate() void QFontDatabasePrivate::invalidate()
{ {
QFontCache::instance()->clear(); QFontCache::instance()->clear();
fallbacksCache.clear();
free(); free();
QGuiApplicationPrivate::platformIntegration()->fontDatabase()->invalidate(); QGuiApplicationPrivate::platformIntegration()->fontDatabase()->invalidate();
emit static_cast<QGuiApplication *>(QCoreApplication::instance())->fontDatabaseChanged(); emit static_cast<QGuiApplication *>(QCoreApplication::instance())->fontDatabaseChanged();
@ -680,8 +718,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fontDatabaseMutex, (QMutex::Recursive))
void qt_cleanupFontDatabase() void qt_cleanupFontDatabase()
{ {
QFontDatabasePrivate *db = privateDb(); QFontDatabasePrivate *db = privateDb();
if (db) if (db) {
db->fallbacksCache.clear();
db->free(); db->free();
}
} }
// used in qfontengine_x11.cpp // 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) 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 // make sure that the db has all fallback families
QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script); QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
QFontDatabasePrivate *db = privateDb();
QStringList::iterator i; QStringList::iterator i;
for (i = retList.begin(); i != retList.end(); ++i) { for (i = retList.begin(); i != retList.end(); ++i) {
@ -818,6 +864,9 @@ QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFo
--i; --i;
} }
} }
db->fallbacksCache.insert(cacheKey, new QStringList(retList));
return 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 \class QDnsLookup
\brief The QDnsLookup class represents a DNS lookup. \brief The QDnsLookup class represents a DNS lookup.

View File

@ -89,6 +89,8 @@ public:
void _q_lookupFinished(const QDnsLookupReply &reply); void _q_lookupFinished(const QDnsLookupReply &reply);
static const char *msgNoIpV6NameServerAdresses;
bool isFinished; bool isFinished;
QString name; QString name;
QDnsLookup::Type type; 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]; ns->sin6_addr.s6_addr[i] = ipv6Address[i];
} }
#else #else
qWarning("IPv6 addresses for nameservers is currently not supported"); qWarning("%s", QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
reply->error = QDnsLookup::ResolverError; reply->error = QDnsLookup::ResolverError;
reply->errorString = tr("IPv6 addresses for nameservers is currently not supported"); reply->errorString = tr(QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
return; return;
#endif #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 // For supoprting IPv6 nameserver addresses, we'll need to switch
// from DnsQuey() to DnsQueryEx() as it supports passing an IPv6 // from DnsQuey() to DnsQueryEx() as it supports passing an IPv6
// address in the nameserver list // address in the nameserver list
qWarning("IPv6 addresses for nameservers are currently not supported"); qWarning("%s", QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
reply->error = QDnsLookup::ResolverError; reply->error = QDnsLookup::ResolverError;
reply->errorString = tr("IPv6 addresses for nameservers are currently not supported"); reply->errorString = tr(QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
return; return;
} }
} }

View File

@ -360,10 +360,15 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
{ {
QList<QNetworkInterfacePrivate *> interfaces; QList<QNetworkInterfacePrivate *> interfaces;
QSet<QString> seenInterfaces; QSet<QString> seenInterfaces;
QVarLengthArray<int, 16> seenIndexes; // faster than QSet<int>
// on Linux, AF_PACKET addresses carry the hardware address and interface index; // On Linux, glibc, uClibc and MUSL obtain the address listing via two
// scan for them first (they're usually first, but we have no guarantee this // netlink calls: first an RTM_GETLINK to obtain the interface listing,
// will be the case forever) // 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) { for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
if (ptr->ifa_addr && ptr->ifa_addr->sa_family == AF_PACKET) { if (ptr->ifa_addr && ptr->ifa_addr->sa_family == AF_PACKET) {
sockaddr_ll *sll = (sockaddr_ll *)ptr->ifa_addr; 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->flags = convertFlags(ptr->ifa_flags);
iface->hardwareAddress = iface->makeHwAddress(sll->sll_halen, (uchar*)sll->sll_addr); 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); seenInterfaces.insert(iface->name);
} }
} }
// see if we missed anything: // 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) { for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
if (ptr->ifa_addr && ptr->ifa_addr->sa_family != AF_PACKET) { if (ptr->ifa_addr && ptr->ifa_addr->sa_family != AF_PACKET) {
QString name = QString::fromLatin1(ptr->ifa_name); QString name = QString::fromLatin1(ptr->ifa_name);
if (seenInterfaces.contains(name)) if (seenInterfaces.contains(name))
continue; continue;
int ifindex = if_nametoindex(ptr->ifa_name);
if (seenIndexes.contains(ifindex))
continue;
QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate; QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
interfaces << iface; interfaces << iface;
iface->name = name; iface->name = name;
iface->flags = convertFlags(ptr->ifa_flags); 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); interfaces = createInterfaces(interfaceListing);
for (ifaddrs *ptr = interfaceListing; ptr; ptr = ptr->ifa_next) { for (ifaddrs *ptr = interfaceListing; ptr; ptr = ptr->ifa_next) {
// Get the interface index // Find the interface
QString name = QString::fromLatin1(ptr->ifa_name); QString name = QString::fromLatin1(ptr->ifa_name);
QNetworkInterfacePrivate *iface = 0; QNetworkInterfacePrivate *iface = 0;
QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin(); QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
@ -479,6 +491,18 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
iface = *if_it; iface = *if_it;
break; 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) { if (!iface) {
// skip all non-IP interfaces // skip all non-IP interfaces
continue; continue;

View File

@ -96,7 +96,7 @@ public:
qint64 read(char *data, qint64 maxlen); qint64 read(char *data, qint64 maxlen);
qint64 write(const char *data, qint64 len); 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); qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header);
bool hasPendingDatagrams() const; bool hasPendingDatagrams() const;
qint64 pendingDatagramSize() const; qint64 pendingDatagramSize() const;

View File

@ -60,6 +60,15 @@ public:
if (func) if (func)
func(window, type); 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) 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. 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 \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/QWindow>
#include <QtGui/QPainter> #include <QtGui/QPainter>
#include <qpa/qplatformbackingstore.h> #include <qpa/qplatformbackingstore.h>
#include <private/qwindow_p.h>
#include "qopenglcompositorbackingstore_p.h" #include "qopenglcompositorbackingstore_p.h"
#include "qopenglcompositor_p.h" #include "qopenglcompositor_p.h"
@ -198,6 +199,8 @@ void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegi
dstCtx->makeCurrent(dstWin); dstCtx->makeCurrent(dstWin);
QWindowPrivate::get(window)->lastComposeTime.start();
m_textures->clear(); m_textures->clear();
for (int i = 0; i < textures->count(); ++i) for (int i = 0; i < textures->count(); ++i)
m_textures->appendTexture(textures->source(i), textures->textureId(i), textures->geometry(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 // check if XCOMPOSEFILE points to a Compose file
if (qEnvironmentVariableIsSet("XCOMPOSEFILE")) { if (qEnvironmentVariableIsSet("XCOMPOSEFILE")) {
QString path(qgetenv("XCOMPOSEFILE")); const QString path = QFile::decodeName(qgetenv("XCOMPOSEFILE"));
if (path.endsWith(QLatin1String("Compose"))) if (QFile::exists(path))
return path; return path;
else 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 // check if users home directory has a file named .XCompose

View File

@ -34,6 +34,7 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <pthread.h> #include <pthread.h>
#include <semaphore.h>
#include <qplugin.h> #include <qplugin.h>
#include <qdebug.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 Main m_main = nullptr;
static void *m_mainLibraryHnd = nullptr; static void *m_mainLibraryHnd = nullptr;
static QList<QByteArray> m_applicationParams; static QList<QByteArray> m_applicationParams;
pthread_t m_qtAppThread = 0;
static sem_t m_exitSemaphore, m_terminateSemaphore;
struct SurfaceData struct SurfaceData
{ {
@ -454,6 +457,10 @@ static void *startMainMethod(void */*data*/)
if (vm != 0) if (vm != 0)
vm->DetachCurrentThread(); 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 // We must call exit() to ensure that all global objects will be destructed
exit(ret); exit(ret);
return 0; return 0;
@ -503,8 +510,13 @@ static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring para
return false; return false;
} }
pthread_t appThread; if (sem_init(&m_exitSemaphore, 0, 0) == -1)
return pthread_create(&appThread, nullptr, startMainMethod, nullptr) == 0; 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*/) static void terminateQt(JNIEnv *env, jclass /*clazz*/)
{ {
sem_wait(&m_terminateSemaphore);
sem_destroy(&m_terminateSemaphore);
env->DeleteGlobalRef(m_applicationClass); env->DeleteGlobalRef(m_applicationClass);
env->DeleteGlobalRef(m_classLoaderObject); env->DeleteGlobalRef(m_classLoaderObject);
if (m_resourcesObj) if (m_resourcesObj)
@ -535,6 +549,8 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/)
m_androidPlatformIntegration = nullptr; m_androidPlatformIntegration = nullptr;
delete m_androidAssetsFileEngineHandler; delete m_androidAssetsFileEngineHandler;
m_androidAssetsFileEngineHandler = nullptr; 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) 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(';'))); result.append(QString(qgetenv("QT_ANDROID_FONTS_SERIF")).split(QLatin1Char(';')));
else else
result.append(QString(qgetenv("QT_ANDROID_FONTS")).split(QLatin1Char(';'))); 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; return result;
} }

View File

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

View File

@ -45,12 +45,15 @@
QIOSContext::QIOSContext(QOpenGLContext *context) QIOSContext::QIOSContext(QOpenGLContext *context)
: QPlatformOpenGLContext() : QPlatformOpenGLContext()
, m_sharedContext(static_cast<QIOSContext *>(context->shareHandle())) , m_sharedContext(static_cast<QIOSContext *>(context->shareHandle()))
, m_eaglContext(0)
, m_format(context->format()) , m_format(context->format())
{ {
m_format.setRenderableType(QSurfaceFormat::OpenGLES); m_format.setRenderableType(QSurfaceFormat::OpenGLES);
m_eaglContext = [[EAGLContext alloc]
initWithAPI:EAGLRenderingAPI(m_format.majorVersion()) EAGLSharegroup *shareGroup = m_sharedContext ? [m_sharedContext->m_eaglContext sharegroup] : nil;
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) { if (m_eaglContext != nil) {
EAGLContext *originalContext = [EAGLContext currentContext]; EAGLContext *originalContext = [EAGLContext currentContext];

View File

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

View File

@ -318,7 +318,11 @@
// a regular responder transfer to another window. In the former case, iOS // 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 // will set the new first-responder to our next-responder, and in the latter
// case we'll have an active responder candidate. // 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 // We have resigned the keyboard, and transferred first responder back to the parent view
Q_ASSERT(!FirstResponderCandidate::currentCandidate()); Q_ASSERT(!FirstResponderCandidate::currentCandidate());
if ([self currentImeState:Qt::ImEnabled].toBool()) { if ([self currentImeState:Qt::ImEnabled].toBool()) {
@ -364,6 +368,32 @@
[self sendKeyPressRelease:key modifiers:modifiers]; [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 - (void)cut:(id)sender
{ {
Q_UNUSED(sender); Q_UNUSED(sender);
@ -382,6 +412,13 @@
[self sendShortcut:QKeySequence::Paste]; [self sendShortcut:QKeySequence::Paste];
} }
- (void)select:(id)sender
{
Q_UNUSED(sender);
[self sendShortcut:QKeySequence::MoveToPreviousWord];
[self sendShortcut:QKeySequence::SelectNextWord];
}
- (void)selectAll:(id)sender - (void)selectAll:(id)sender
{ {
Q_UNUSED(sender); Q_UNUSED(sender);
@ -580,7 +617,8 @@
- (UITextPosition *)endOfDocument - (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]; return [QUITextPosition positionWithIndex:endPosition];
} }
@ -611,9 +649,18 @@
- (NSString *)textInRange:(UITextRange *)range - (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 s = static_cast<QUITextPosition *>([range start]).index;
int e = static_cast<QUITextPosition *>([range end]).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 - (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange
@ -882,6 +929,14 @@
if ([text isEqualToString:@"\n"]) { if ([text isEqualToString:@"\n"]) {
[self sendKeyPressRelease:Qt::Key_Return modifiers:Qt::NoModifier]; [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 if (self.returnKeyType == UIReturnKeyDone || self.returnKeyType == UIReturnKeyGo
|| self.returnKeyType == UIReturnKeySend || self.returnKeyType == UIReturnKeySearch) || self.returnKeyType == UIReturnKeySend || self.returnKeyType == UIReturnKeySearch)
[self resignFirstResponder]; [self resignFirstResponder];

View File

@ -96,7 +96,12 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion &region,
RECT dirty = {dirtyRect.x(), dirtyRect.y(), RECT dirty = {dirtyRect.x(), dirtyRect.y(),
dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()}; dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()};
UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, &ptDst, &size, m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA, &dirty}; 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 { } else {
QWindowsContext::user32dll.updateLayeredWindow(rw->handle(), NULL, &ptDst, &size, m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA); 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; quint16 stringOffset;
} NAME_RECORD; } 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); QFile f(filename);
QString retVal; QString retVal;
@ -200,6 +207,7 @@ static QString fontNameFromTTFile(const QString &filename)
qint64 bytesToRead; qint64 bytesToRead;
if (f.open(QIODevice::ReadOnly)) { if (f.open(QIODevice::ReadOnly)) {
f.seek(startPos);
OFFSET_TABLE ttOffsetTable; OFFSET_TABLE ttOffsetTable;
bytesToRead = sizeof(OFFSET_TABLE); bytesToRead = sizeof(OFFSET_TABLE);
bytesRead = f.read((char*)&ttOffsetTable, bytesToRead); bytesRead = f.read((char*)&ttOffsetTable, bytesToRead);
@ -280,6 +288,37 @@ static QString fontNameFromTTFile(const QString &filename)
return retVal; 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 fontSettingsOrganization() { return QStringLiteral("Qt-Project"); }
static inline QString fontSettingsApplication() { return QStringLiteral("Qtbase"); } static inline QString fontSettingsApplication() { return QStringLiteral("Qtbase"); }
static inline QString fontSettingsGroup() { return QStringLiteral("CEFontCache"); } 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 //empty the cache first, as it seems that it is dirty
settings.remove(QString()); 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()) { while (it.hasNext()) {
const QString fontFile = it.next(); const QString fontFile = it.next();
const QString fontName = fontNameFromTTFile(fontFile); QStringList fontNames;
if (fontName.isEmpty()) const QChar c = fontFile[fontFile.size() - 1];
continue; if (c == lowerF || c == upperF)
fontCache.insert(fontName, fontFile); fontNames << fontNameFromTTFile(fontFile);
settings.setValue(fontName, 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)) { if (localizedName(fontName)) {
QString englishFontName = getEnglishName(fontName); QString englishFontName = getEnglishName(fontName);
fontCache.insert(englishFontName, fontFile); fontCache.insert(englishFontName, fontFile);
settings.setValue(englishFontName, fontFile); settings.setValue(englishFontName, fontFile);
}
} }
} }
settings.endGroup(); settings.endGroup();
@ -675,7 +722,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF
result.append(QWindowsFontDatabase::extraTryFontsForFamily(family)); 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 qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
<< script << result; << script << result;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -428,6 +428,21 @@ QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handl
return engine; 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) void QWinRTFontDatabase::releaseHandle(void *handle)
{ {
if (!handle) if (!handle)

View File

@ -60,6 +60,8 @@ public:
void populateFontDatabase() Q_DECL_OVERRIDE; void populateFontDatabase() Q_DECL_OVERRIDE;
void populateFamily(const QString &familyName) Q_DECL_OVERRIDE; void populateFamily(const QString &familyName) Q_DECL_OVERRIDE;
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) 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; void releaseHandle(void *handle) Q_DECL_OVERRIDE;
private: private:
QHash<IDWriteFontFile *, FontDescription> m_fonts; QHash<IDWriteFontFile *, FontDescription> m_fonts;

View File

@ -179,42 +179,6 @@ QXcbScreen* QXcbConnection::findScreenForOutput(xcb_window_t rootWindow, xcb_ran
return 0; 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) QXcbVirtualDesktop* QXcbConnection::virtualDesktopForRootWindow(xcb_window_t rootWindow)
{ {
foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops) { foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops) {
@ -237,8 +201,9 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
// Not for us // Not for us
return; return;
qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc;
QXcbScreen *screen = findScreenForCrtc(crtc.window, 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 // 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 // CRTC with node mode could mean that output has been disabled, and we'll
// get RRNotifyOutputChange notification for that. // 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) { if (screen && output.connection == XCB_RANDR_CONNECTION_DISCONNECTED) {
qCDebug(lcQpaScreen) << "screen" << screen->name() << "has been disconnected"; qCDebug(lcQpaScreen) << "screen" << screen->name() << "has been disconnected";
destroyScreen(screen);
// 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.
} else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) { } else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) {
// New XRandR output is available and it's enabled // New XRandR output is available and it's enabled
if (output.crtc != XCB_NONE && output.mode != XCB_NONE) { 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( QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL)); xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
screen = createScreen(virtualDesktop, output.output, outputInfo.data()); // Find a fake screen
qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled"; foreach (QPlatformScreen *scr, virtualDesktop->screens()) {
QXcbScreen *xcbScreen = (QXcbScreen *)scr;
if (xcbScreen->output() == XCB_NONE) {
screen = xcbScreen;
break;
}
}
screen->setPrimary(checkOutputIsPrimary(output.window, output.output)); if (screen) {
virtualDesktop->addScreen(screen); QString nameWas = screen->name();
m_screens << screen; // Transform the fake screen into a physical screen
QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary()); screen->setOutput(output.output, outputInfo.data());
updateScreen(screen, output);
// Windows which had null screens have already had expose events by now. qCDebug(lcQpaScreen) << "output" << screen->name()
// They need to be told the screen is back, it's OK to render. << "is connected and enabled; was fake:" << nameWas;
foreach (QWindow *window, QGuiApplication::topLevelWindows()) { } else {
QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle()); screen = createScreen(virtualDesktop, output, outputInfo.data());
if (xcbWin) qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
xcbWin->maybeSetScreen(screen);
} }
} }
// else ignore disabled screens
} else if (screen) { } else if (screen) {
// Screen has been disabled -> remove
if (output.crtc == XCB_NONE && output.mode == XCB_NONE) { 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_cookie_t outputInfoCookie =
xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp); xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp);
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo( QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL)); xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
if (outputInfo->crtc == XCB_NONE) { if (outputInfo->crtc == XCB_NONE) {
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled"; qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled";
m_screens.removeOne(screen); destroyScreen(screen);
virtualDesktop->removeScreen(screen);
QXcbIntegration::instance()->destroyScreen(screen);
} else { } else {
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been temporarily disabled for the mode switch"; 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 { } else {
// Just update existing screen updateScreen(screen, output);
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);
}
qCDebug(lcQpaScreen) << "output has changed" << screen; 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()) if (!m_screens.isEmpty())
qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name(); m_screens.first()->setPrimary(false);
else
qCDebug(lcQpaScreen) << "no outputs"; 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); xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
int xcbScreenNumber = 0; // screen number in the xcb sense int xcbScreenNumber = 0; // screen number in the xcb sense
QXcbScreen* primaryScreen = Q_NULLPTR; QXcbScreen *primaryScreen = Q_NULLPTR;
bool hasOutputs = false;
while (it.rem) { while (it.rem) {
// Each "screen" in xcb terminology is a virtual desktop, // Each "screen" in xcb terminology is a virtual desktop,
// potentially a collection of separate juxtaposed monitors. // potentially a collection of separate juxtaposed monitors.
@ -348,8 +386,6 @@ void QXcbConnection::initializeScreens()
xcb_screen_t *xcbScreen = it.data; xcb_screen_t *xcbScreen = it.data;
QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber); QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
m_virtualDesktops.append(virtualDesktop); m_virtualDesktops.append(virtualDesktop);
QList<QPlatformScreen *> siblings;
int outputCount = 0;
if (has_randr_extension) { if (has_randr_extension) {
xcb_generic_error_t *error = NULL; xcb_generic_error_t *error = NULL;
// RRGetScreenResourcesCurrent is fast but it may return nothing if the // RRGetScreenResourcesCurrent is fast but it may return nothing if the
@ -366,7 +402,7 @@ void QXcbConnection::initializeScreens()
} else { } else {
xcb_timestamp_t timestamp; xcb_timestamp_t timestamp;
xcb_randr_output_t *outputs = Q_NULLPTR; 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) { if (outputCount) {
timestamp = resources_current->config_timestamp; timestamp = resources_current->config_timestamp;
outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.data()); 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"); qWarning("failed to get the primary output of the screen");
free(error); free(error);
} else { } else {
QList<QPlatformScreen *> siblings;
for (int i = 0; i < outputCount; i++) { for (int i = 0; i < outputCount; i++) {
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output( QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output(
xcb_randr_get_output_info_reply(xcb_connection(), xcb_randr_get_output_info_reply(xcb_connection(),
@ -416,9 +453,8 @@ void QXcbConnection::initializeScreens()
continue; continue;
} }
QXcbScreen *screen = createScreen(virtualDesktop, outputs[i], output.data()); QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.data());
siblings << screen; siblings << screen;
hasOutputs = true;
m_screens << screen; m_screens << screen;
// There can be multiple outputs per screen, use either // 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); xcb_screen_next(&it);
++xcbScreenNumber; ++xcbScreenNumber;
} // for each xcb screen } // for each xcb screen
@ -447,39 +495,25 @@ void QXcbConnection::initializeScreens()
foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops) foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops)
virtualDesktop->subscribeToXFixesSelectionNotify(); virtualDesktop->subscribeToXFixesSelectionNotify();
// If there's no randr extension, or there was some error above, or we found a if (m_virtualDesktops.isEmpty()) {
// screen which doesn't have outputs for some other reason (e.g. on VNC or ssh -X), qFatal("QXcbConnection: no screens available");
// but the dimensions are known anyway, and we don't already have any lingering } else {
// (possibly disconnected) screens, then showing windows should be possible, // Ensure the primary screen is first on the list
// so create one screen. (QTBUG-31389) if (primaryScreen) {
QXcbVirtualDesktop *virtualDesktop = m_virtualDesktops.value(0); if (m_screens.first() != primaryScreen) {
if (virtualDesktop && !hasOutputs && !virtualDesktop->size().isEmpty() && m_screens.isEmpty()) { m_screens.removeOne(primaryScreen);
QXcbScreen *screen = createScreen(virtualDesktop, 0, Q_NULLPTR); m_screens.prepend(primaryScreen);
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);
} }
}
// Push the screens to QApplication // Push the screens to QGuiApplication
QXcbIntegration *integration = QXcbIntegration::instance(); foreach (QXcbScreen *screen, m_screens) {
foreach (QXcbScreen* screen, m_screens) { qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")";
qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ')'; QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
integration->screenAdded(screen, screen->isPrimary()); }
}
if (!m_screens.isEmpty())
qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name(); qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
}
} }
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName) QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName)
@ -553,9 +587,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
initializeXFixes(); initializeXFixes();
initializeScreens(); initializeScreens();
if (Q_UNLIKELY(m_screens.isEmpty()))
qFatal("QXcbConnection: no screens available");
initializeXRender(); initializeXRender();
m_xi2Enabled = false; m_xi2Enabled = false;
#if defined(XCB_USE_XINPUT2) #if defined(XCB_USE_XINPUT2)

View File

@ -518,15 +518,17 @@ private:
void initializeXShape(); void initializeXShape();
void initializeXKB(); void initializeXKB();
void handleClientMessageEvent(const xcb_client_message_event_t *event); 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* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc);
QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output); QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output);
QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow); 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); 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 compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const;
bool m_xi2Enabled; bool m_xi2Enabled;

View File

@ -406,6 +406,9 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
#endif // XCB_USE_XINPUT22 #endif // XCB_USE_XINPUT22
case XIValuatorClass: { case XIValuatorClass: {
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo); 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)) if (vci->label == atom(QXcbAtom::AbsMTPositionX))
caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition; caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition;
else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor))
@ -414,16 +417,16 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
caps |= QTouchDevice::Pressure; caps |= QTouchDevice::Pressure;
else if (vci->label == atom(QXcbAtom::RelX)) { else if (vci->label == atom(QXcbAtom::RelX)) {
hasRelativeCoords = true; 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)) { } else if (vci->label == atom(QXcbAtom::RelY)) {
hasRelativeCoords = true; 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)) { } else if (vci->label == atom(QXcbAtom::AbsX)) {
caps |= QTouchDevice::Position; 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)) { } else if (vci->label == atom(QXcbAtom::AbsY)) {
caps |= QTouchDevice::Position; 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; break;
} }

View File

@ -81,6 +81,13 @@ void QXcbVirtualDesktop::addScreen(QPlatformScreen *s)
((QXcbScreen *) s)->isPrimary() ? m_screens.prepend(s) : m_screens.append(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 QXcbXSettings *QXcbVirtualDesktop::xSettings() const
{ {
if (!m_xSettings) { if (!m_xSettings) {
@ -149,16 +156,15 @@ void QXcbVirtualDesktop::updateWorkArea()
} }
QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop, QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output, xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output)
QString outputName)
: QXcbObject(connection) : QXcbObject(connection)
, m_virtualDesktop(virtualDesktop) , m_virtualDesktop(virtualDesktop)
, m_output(outputId) , m_output(outputId)
, m_crtc(output ? output->crtc : 0) , m_crtc(output ? output->crtc : XCB_NONE)
, m_mode(XCB_NONE) , m_mode(XCB_NONE)
, m_primary(false) , m_primary(false)
, m_rotation(XCB_RANDR_ROTATION_ROTATE_0) , 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_outputSizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize())
, m_virtualSize(virtualDesktop->size()) , m_virtualSize(virtualDesktop->size())
, m_virtualSizeMillimeters(virtualDesktop->physicalSize()) , m_virtualSizeMillimeters(virtualDesktop->physicalSize())
@ -266,6 +272,22 @@ QXcbScreen::~QXcbScreen()
delete m_cursor; 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 QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
{ {
@ -390,6 +412,16 @@ QPlatformCursor *QXcbScreen::cursor() const
return m_cursor; 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 \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); updateGeometry(change_event->timestamp);
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), m_orientation); QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), m_orientation);
QDpi ldpi = logicalDpi(); QDpi ldpi = logicalDpi();
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QPlatformScreen::screen(), ldpi.first, ldpi.second); 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) void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)

View File

@ -72,6 +72,7 @@ public:
void setScreens(QList<QPlatformScreen *> sl) { m_screens = sl; } void setScreens(QList<QPlatformScreen *> sl) { m_screens = sl; }
void removeScreen(QPlatformScreen *s) { m_screens.removeOne(s); } void removeScreen(QPlatformScreen *s) { m_screens.removeOne(s); }
void addScreen(QPlatformScreen *s); void addScreen(QPlatformScreen *s);
void setPrimaryScreen(QPlatformScreen *s);
QXcbXSettings *xSettings() const; QXcbXSettings *xSettings() const;
@ -101,10 +102,11 @@ class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen
{ {
public: public:
QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop, QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output, xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *outputInfo);
QString outputName);
~QXcbScreen(); ~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; 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; 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_crtc_t crtc() const { return m_crtc; }
xcb_randr_mode_t mode() const { return m_mode; } 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); void windowShown(QXcbWindow *window);
QString windowManagerName() const { return m_windowManagerName; } QString windowManagerName() const { return m_windowManagerName; }
bool syncRequestSupported() const { return m_syncRequestSupported; } bool syncRequestSupported() const { return m_syncRequestSupported; }

View File

@ -143,7 +143,7 @@ const quint32 XEMBED_VERSION = 0;
QXcbScreen *QXcbWindow::parentScreen() 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 // 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) QXcbWindow::QXcbWindow(QWindow *window)
: QPlatformWindow(window) : QPlatformWindow(window)
, m_window(0) , m_window(0)
, m_xcbScreen(0)
, m_syncCounter(0) , m_syncCounter(0)
, m_gravity(XCB_GRAVITY_STATIC) , m_gravity(XCB_GRAVITY_STATIC)
, m_mapped(false) , m_mapped(false)
@ -322,7 +321,6 @@ void QXcbWindow::create()
QRect rect = windowGeometry(); QRect rect = windowGeometry();
QXcbScreen *platformScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect)); QXcbScreen *platformScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
m_xcbScreen = platformScreen;
if (type == Qt::Desktop) { if (type == Qt::Desktop) {
m_window = platformScreen->root(); m_window = platformScreen->root();
m_depth = platformScreen->screen()->root_depth; m_depth = platformScreen->screen()->root_depth;
@ -624,27 +622,18 @@ void QXcbWindow::destroy()
m_pendingSyncRequest->invalidate(); 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) void QXcbWindow::setGeometry(const QRect &rect)
{ {
QPlatformWindow::setGeometry(rect); QPlatformWindow::setGeometry(rect);
propagateSizeHints(); propagateSizeHints();
QXcbScreen *currentScreen = m_xcbScreen; QXcbScreen *currentScreen = xcbScreen();
QXcbScreen *newScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect)); QXcbScreen *newScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
if (!newScreen) if (!newScreen)
newScreen = xcbScreen(); newScreen = xcbScreen();
m_xcbScreen = newScreen;
const QRect wmGeometry = windowToWmGeometry(rect); const QRect wmGeometry = windowToWmGeometry(rect);
if (newScreen && newScreen != currentScreen) if (newScreen && newScreen != currentScreen)
@ -848,15 +837,13 @@ void QXcbWindow::hide()
Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window)); Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window));
// send synthetic UnmapNotify event according to icccm 4.1.4 // send synthetic UnmapNotify event according to icccm 4.1.4
if (xcbScreen()) { xcb_unmap_notify_event_t event;
xcb_unmap_notify_event_t event; event.response_type = XCB_UNMAP_NOTIFY;
event.response_type = XCB_UNMAP_NOTIFY; event.event = xcbScreen()->root();
event.event = xcbScreen()->root(); event.window = m_window;
event.window = m_window; event.from_configure = false;
event.from_configure = false; Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(),
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_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
}
xcb_flush(xcb_connection()); 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[3] = 0;
event.data.data32[4] = 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)); 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(); xcb_parent_id = qXcbParent->xcb_window();
m_embedded = qXcbParent->window()->type() == Qt::ForeignWindow; m_embedded = qXcbParent->window()->type() == Qt::ForeignWindow;
} else { } else {
if (!xcbScreen())
return;
xcb_parent_id = xcbScreen()->root(); xcb_parent_id = xcbScreen()->root();
m_embedded = false; m_embedded = false;
} }
@ -2005,7 +1988,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
{ {
bool fromSendEvent = (event->response_type & 0x80); bool fromSendEvent = (event->response_type & 0x80);
QPoint pos(event->x, event->y); QPoint pos(event->x, event->y);
if (!parent() && !fromSendEvent && xcbScreen()) { if (!parent() && !fromSendEvent) {
// Do not trust the position, query it instead. // Do not trust the position, query it instead.
xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(), xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(),
xcbScreen()->root(), 0, 0); 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)); // The original geometry requested by setGeometry() might be different
QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(rect); // from what we end up with after applying window constraints.
QRect requestedGeometry = geometry();
QXcbScreen *currentScreen = m_xcbScreen; const QRect actualGeometry = QRect(pos, QSize(event->width, event->height));
m_xcbScreen = static_cast<QXcbScreen*>(newScreen); QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(actualGeometry);
if (!newScreen) if (!newScreen)
return; return;
QPlatformWindow::setGeometry(rect); // Persist the actual geometry so that QWindow::geometry() can
QWindowSystemInterface::handleGeometryChange(window(), rect); // be queried in the resize event.
if (newScreen != currentScreen) QPlatformWindow::setGeometry(actualGeometry);
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
if (m_mapped) // FIXME: In the case of the requestedGeometry not matching the actualGeometry due
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); // 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) if (m_usingSyncProtocol && m_syncState == SyncReceived)
m_syncState = SyncAndConfigureReceived; m_syncState = SyncAndConfigureReceived;
@ -2298,8 +2298,6 @@ void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
return; return;
const QPoint local(event->event_x, event->event_y); const QPoint local(event->event_x, event->event_y);
if (!xcbScreen())
return;
QPoint global = QPoint(event->root_x, event->root_y); QPoint global = QPoint(event->root_x, event->root_y);
QWindowSystemInterface::handleEnterEvent(window(), local, global); QWindowSystemInterface::handleEnterEvent(window(), local, global);
} }
@ -2317,8 +2315,6 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
if (enterWindow) { if (enterWindow) {
QPoint local(enter->event_x, enter->event_y); QPoint local(enter->event_x, enter->event_y);
if (!xcbScreen())
return;
QPoint global = QPoint(event->root_x, event->root_y); QPoint global = QPoint(event->root_x, event->root_y);
QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global); 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); connection()->setTime(event->time);
const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE; 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 (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
if (propertyDeleted) if (propertyDeleted)
@ -2655,8 +2649,6 @@ bool QXcbWindow::needsSync() const
void QXcbWindow::postSyncWindowRequest() void QXcbWindow::postSyncWindowRequest()
{ {
if (!xcbScreen())
return;
if (!m_pendingSyncRequest) { if (!m_pendingSyncRequest) {
QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this); QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this);
m_pendingSyncRequest = e; m_pendingSyncRequest = e;

View File

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

View File

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

View File

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

View File

@ -76,7 +76,7 @@
advises against will produce more easily comprehensible software. advises against will produce more easily comprehensible software.
Doing what it tells you to do may also help. 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, Microsoft Windows User Experience}}, ISBN 1-55615-679-0,
is Microsoft's look and feel bible. Indispensable for everyone who is Microsoft's look and feel bible. Indispensable for everyone who
has customers that worship Microsoft, and it's quite good, too. 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 activated when the user clicks or double clicks on it, depending on the
system configuration. It is also activated when the user presses 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 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 \value TextHeuristicRole This action should be put in the application menu based on the action's text
as described in the QMenuBar documentation. as described in the QMenuBar documentation.
\value ApplicationSpecificRole This action should be put in the application menu with an application specific role \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 \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 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}). \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 \since 4.2
This indicates what role the action serves in the application menu on Mac 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 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 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) if (!widget)
return; 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) { switch (updateTime) {
case UpdateLater: case UpdateLater:
updateRequestSent = true; updateRequestSent = true;
@ -621,7 +641,11 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget,
const QRect widgetRect = widget->d_func()->effectiveRectFor(rect); 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 (qt_region_strictContains(dirty, translatedRect)) {
if (updateTime == UpdateNow) if (updateTime == UpdateNow)
sendUpdateRequest(tlw, updateTime); sendUpdateRequest(tlw, updateTime);

View File

@ -1816,7 +1816,8 @@ void QDockAreaLayoutInfo::saveState(QDataStream &stream) const
stream << flags; stream << flags;
if (w->isWindow()) { 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 { } else {
stream << item.pos << item.size << pick(o, item.minimumSize()) stream << item.pos << item.size << pick(o, item.minimumSize())
<< pick(o, item.maximumSize()); << pick(o, item.maximumSize());

View File

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

View File

@ -140,6 +140,8 @@ public:
hr = applicationFactory->CreateInstance(this, &base, &core); hr = applicationFactory->CreateInstance(this, &base, &core);
RETURN_VOID_IF_FAILED("Failed to create application container instance"); RETURN_VOID_IF_FAILED("Failed to create application container instance");
pidFile = INVALID_HANDLE_VALUE;
} }
~AppContainer() ~AppContainer()
@ -157,6 +159,13 @@ public:
int argc = app->args.count(); int argc = app->args.count();
char **argv = app->args.data(); char **argv = app->args.data();
const int res = main(argc, argv); 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(); app->core->Exit();
return res; return res;
}, this, CREATE_SUSPENDED, nullptr); }, 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 develMode = false;
bool debugWait = false; bool debugWait = false;
foreach (const char *arg, args) { foreach (const char *arg, args) {
@ -248,11 +260,10 @@ private:
.absoluteFilePath(QString::number(uint(GetCurrentProcessId())) + QStringLiteral(".pid")); .absoluteFilePath(QString::number(uint(GetCurrentProcessId())) + QStringLiteral(".pid"));
CREATEFILE2_EXTENDED_PARAMETERS params = { CREATEFILE2_EXTENDED_PARAMETERS params = {
sizeof(CREATEFILE2_EXTENDED_PARAMETERS), 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 pidFile = CreateFile2(reinterpret_cast<LPCWSTR>(pidFileName.utf16()),
CreateFile2(reinterpret_cast<LPCWSTR>(pidFileName.utf16()), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS, &params);
0, FILE_SHARE_READ|FILE_SHARE_DELETE, CREATE_ALWAYS, &params);
// Install the develMode message handler // Install the develMode message handler
#ifndef Q_OS_WINPHONE #ifndef Q_OS_WINPHONE
defaultMessageHandler = qInstallMessageHandler(devMessageHandler); defaultMessageHandler = qInstallMessageHandler(devMessageHandler);
@ -315,6 +326,7 @@ private:
QByteArray commandLine; QByteArray commandLine;
QVarLengthArray<char *> args; QVarLengthArray<char *> args;
HANDLE mainThread; HANDLE mainThread;
HANDLE pidFile;
}; };
// Main entry point for Appx containers // Main entry point for Appx containers

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
TEMPLATE = subdirs TEMPLATE = subdirs
SUBDIRS += test \ SUBDIRS += test
syslocaleapp !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