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:
commit
beb65dcd79
@ -764,7 +764,7 @@ while ( @ARGV ) {
|
||||
$var = "version";
|
||||
$val = shift @ARGV;
|
||||
} elsif($arg =~/^-/) {
|
||||
print STDERR "Unknown option: $arg\n\n" if (!$var);
|
||||
print STDERR "ERROR: Unknown option: $arg\n\n" if (!$var);
|
||||
showUsage();
|
||||
} else {
|
||||
$basedir = locateSyncProfile($arg);
|
||||
@ -777,7 +777,7 @@ while ( @ARGV ) {
|
||||
|
||||
#do something
|
||||
if(!$var || $var eq "show_help") {
|
||||
print STDERR "Unknown option: $arg\n\n" if (!$var);
|
||||
print STDERR "ERROR: Unknown option: $arg\n\n" if (!$var);
|
||||
showUsage();
|
||||
} elsif ($var eq "copy") {
|
||||
if($val eq "yes") {
|
||||
|
@ -36,6 +36,7 @@ HTML.headerscripts = \
|
||||
" <script type=\"text/javascript\" src=\"scripts/extras.js\"></script>\n" \
|
||||
" <script type=\"text/javascript\">\n" \
|
||||
" \$(function(){\n" \
|
||||
" \$(\"#footer\").load(\"/style/qt-footer.html\");\n" \
|
||||
" \$(\"#sidebar-content\").load(\"style/qt5-sidebar.html\");\n" \
|
||||
" });\n" \
|
||||
" </script>\n" \
|
||||
|
@ -1258,15 +1258,15 @@ li a.active {
|
||||
color:#404244;
|
||||
line-height:1.16em
|
||||
}
|
||||
.mainContent table p {
|
||||
margin:0px;
|
||||
padding:0px
|
||||
}
|
||||
.mainContent table p {
|
||||
margin:0px;
|
||||
padding:0px;
|
||||
max-width:initial;
|
||||
min-height:2em
|
||||
}
|
||||
.mainContent table p.centerAlign {
|
||||
text-align:center
|
||||
}
|
||||
.context h2 {
|
||||
font-size:2.1875em
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ Client::Client(QWidget *parent)
|
||||
//! [4]
|
||||
|
||||
QGridLayout *mainLayout = Q_NULLPTR;
|
||||
if (QGuiApplication::styleHints()->showIsFullScreen()) {
|
||||
if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) {
|
||||
QVBoxLayout *outerVerticalLayout = new QVBoxLayout(this);
|
||||
outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
|
||||
QHBoxLayout *outerHorizontalLayout = new QHBoxLayout;
|
||||
|
@ -100,7 +100,7 @@ Server::Server(QWidget *parent)
|
||||
buttonLayout->addStretch(1);
|
||||
|
||||
QVBoxLayout *mainLayout = Q_NULLPTR;
|
||||
if (QGuiApplication::styleHints()->showIsFullScreen()) {
|
||||
if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) {
|
||||
QVBoxLayout *outerVerticalLayout = new QVBoxLayout(this);
|
||||
outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
|
||||
QHBoxLayout *outerHorizontalLayout = new QHBoxLayout;
|
||||
|
@ -98,9 +98,19 @@ int DialogOptionsWidget::value() const
|
||||
Dialog::Dialog(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
||||
QVBoxLayout *verticalLayout;
|
||||
if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) {
|
||||
QHBoxLayout *horizontalLayout = new QHBoxLayout(this);
|
||||
QGroupBox *groupBox = new QGroupBox(QGuiApplication::applicationDisplayName(), this);
|
||||
horizontalLayout->addWidget(groupBox);
|
||||
horizontalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
|
||||
verticalLayout = new QVBoxLayout(groupBox);
|
||||
} else {
|
||||
verticalLayout = new QVBoxLayout(this);
|
||||
}
|
||||
|
||||
QToolBox *toolbox = new QToolBox;
|
||||
mainLayout->addWidget(toolbox);
|
||||
verticalLayout->addWidget(toolbox);
|
||||
|
||||
errorMessageDialog = new QErrorMessage(this);
|
||||
|
||||
@ -291,7 +301,7 @@ Dialog::Dialog(QWidget *parent)
|
||||
layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding), 5, 0);
|
||||
toolbox->addItem(page, tr("Message Boxes"));
|
||||
|
||||
setWindowTitle(tr("Standard Dialogs"));
|
||||
setWindowTitle(QGuiApplication::applicationDisplayName());
|
||||
}
|
||||
|
||||
void Dialog::setInteger()
|
||||
|
@ -39,6 +39,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QStyleHints>
|
||||
#include <QDesktopWidget>
|
||||
#include <QTranslator>
|
||||
#include <QLocale>
|
||||
@ -49,6 +50,7 @@
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
QGuiApplication::setApplicationDisplayName(Dialog::tr("Standard Dialogs"));
|
||||
|
||||
#ifndef QT_NO_TRANSLATION
|
||||
QString translatorFileName = QLatin1String("qt_");
|
||||
@ -59,10 +61,12 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
Dialog dialog;
|
||||
const QRect availableGeometry = QApplication::desktop()->availableGeometry(&dialog);
|
||||
dialog.resize(availableGeometry.width() / 3, availableGeometry.height() * 2 / 3);
|
||||
dialog.move((availableGeometry.width() - dialog.width()) / 2,
|
||||
(availableGeometry.height() - dialog.height()) / 2);
|
||||
if (!QGuiApplication::styleHints()->showIsFullScreen() && !QGuiApplication::styleHints()->showIsMaximized()) {
|
||||
const QRect availableGeometry = QApplication::desktop()->availableGeometry(&dialog);
|
||||
dialog.resize(availableGeometry.width() / 3, availableGeometry.height() * 2 / 3);
|
||||
dialog.move((availableGeometry.width() - dialog.width()) / 2,
|
||||
(availableGeometry.height() - dialog.height()) / 2);
|
||||
}
|
||||
dialog.show();
|
||||
|
||||
return app.exec();
|
||||
|
@ -23,3 +23,6 @@ QMAKE_AR = $${CROSS_COMPILE}ar cqs
|
||||
QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy
|
||||
QMAKE_NM = $${CROSS_COMPILE}nm -P
|
||||
QMAKE_STRIP = $${CROSS_COMPILE}strip
|
||||
|
||||
contains(DISTRO_OPTS, deb-multi-arch): \
|
||||
PKG_CONFIG = $${CROSS_COMPILE}pkg-config
|
||||
|
9
mkspecs/devices/linux-arm-generic-g++/qmake.conf
Normal file
9
mkspecs/devices/linux-arm-generic-g++/qmake.conf
Normal 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)
|
34
mkspecs/devices/linux-arm-generic-g++/qplatformdefs.h
Normal file
34
mkspecs/devices/linux-arm-generic-g++/qplatformdefs.h
Normal 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"
|
@ -90,7 +90,6 @@ load(qt_common)
|
||||
qmlplugindump = qmlplugindump
|
||||
importpath.name = QML2_IMPORT_PATH
|
||||
}
|
||||
qtPrepareTool(QMLPLUGINDUMP, $$qmlplugindump)
|
||||
importpath.value =
|
||||
for(qmod, QTREPOS) {
|
||||
qml1_target: \
|
||||
@ -100,7 +99,9 @@ load(qt_common)
|
||||
exists($$qmod): importpath.value += $$shell_path($$qmod)
|
||||
}
|
||||
importpath.value = $$unique(importpath.value)
|
||||
qtAddToolEnv(QMLPLUGINDUMP, importpath)
|
||||
QT_TOOL_ENV = importpath
|
||||
qtPrepareTool(QMLPLUGINDUMP, $$qmlplugindump)
|
||||
QT_TOOL_ENV =
|
||||
TARGETPATHBASE = $$replace(TARGETPATH, \\.\\d+\$, )
|
||||
qmltypes.target = qmltypes
|
||||
qmltypes.commands = $$QMLPLUGINDUMP -nonrelocatable $$replace(TARGETPATHBASE, /, .) $$IMPORT_VERSION > $$QMLTYPEFILE
|
||||
|
@ -55,6 +55,9 @@ QMAKE_DIR_REPLACE_SANE = PRECOMPILED_DIR OBJECTS_DIR MOC_DIR RCC_DIR UI_DIR
|
||||
cross_compile: \
|
||||
CONFIG += force_bootstrap
|
||||
|
||||
android|ios|winrt: \
|
||||
CONFIG += builtin_testdata
|
||||
|
||||
CONFIG += \
|
||||
create_prl link_prl \
|
||||
prepare_docs qt_docs_targets \
|
||||
|
@ -18,7 +18,19 @@ QMAKE_DOCS_TARGET = $$replace(QMAKE_DOCS, ^(.*/)?(.*)\\.qdocconf$, \\2)
|
||||
isEmpty(QMAKE_DOCS_TARGETDIR): QMAKE_DOCS_TARGETDIR = $$QMAKE_DOCS_TARGET
|
||||
QMAKE_DOCS_OUTPUTDIR = $$QMAKE_DOCS_BASE_OUTDIR/$$QMAKE_DOCS_TARGETDIR
|
||||
|
||||
qtver.name = QT_VERSION
|
||||
qtver.value = $$VERSION
|
||||
isEmpty(qtver.value): qtver.value = $$MODULE_VERSION
|
||||
isEmpty(qtver.value): error("No version for documentation specified.")
|
||||
qtmver.name = QT_VER
|
||||
qtmver.value = $$replace(qtver.value, ^(\\d+\\.\\d+).*$, \\1)
|
||||
qtvertag.name = QT_VERSION_TAG
|
||||
qtvertag.value = $$replace(qtver.value, \.,)
|
||||
qtdocs.name = QT_INSTALL_DOCS
|
||||
qtdocs.value = $$[QT_INSTALL_DOCS/src]
|
||||
QT_TOOL_ENV = qtver qtmver qtvertag qtdocs
|
||||
qtPrepareTool(QDOC, qdoc)
|
||||
QT_TOOL_ENV =
|
||||
QDOC += -outputdir $$QMAKE_DOCS_OUTPUTDIR
|
||||
!build_online_docs: \
|
||||
QDOC += -installdir $$[QT_INSTALL_DOCS]
|
||||
@ -43,17 +55,6 @@ DOC_INDEXES =
|
||||
PREP_DOC_INDEXES += -indexdir $$[QT_INSTALL_DOCS/get]
|
||||
DOC_INDEXES += -indexdir $$[QT_INSTALL_DOCS/get]
|
||||
}
|
||||
qtver.name = QT_VERSION
|
||||
qtver.value = $$VERSION
|
||||
isEmpty(qtver.value): qtver.value = $$MODULE_VERSION
|
||||
isEmpty(qtver.value): error("No version for documentation specified.")
|
||||
qtmver.name = QT_VER
|
||||
qtmver.value = $$replace(qtver.value, ^(\\d+\\.\\d+).*$, \\1)
|
||||
qtvertag.name = QT_VERSION_TAG
|
||||
qtvertag.value = $$replace(qtver.value, \.,)
|
||||
qtdocs.name = QT_INSTALL_DOCS
|
||||
qtdocs.value = $$[QT_INSTALL_DOCS/src]
|
||||
qtAddToolEnv(QDOC, qtver qtmver qtvertag qtdocs)
|
||||
doc_command = $$QDOC $$QMAKE_DOCS
|
||||
prepare_docs {
|
||||
prepare_docs.commands += $$doc_command -prepare $$PREP_DOC_INDEXES -no-link-errors
|
||||
|
@ -73,3 +73,5 @@ DEFINES *= QT_USE_QSTRINGBUILDER
|
||||
cache(QT_TOOL.$${MODULE}.$$var, transient)
|
||||
|
||||
}
|
||||
# The variable is re-used by qtPrepareTool(), and we really don't want that.
|
||||
unset(QT_TOOL_ENV)
|
||||
|
@ -79,7 +79,7 @@ isEmpty(BUILDS)|build_pass {
|
||||
INSTALLS += target
|
||||
}
|
||||
|
||||
contains(INSTALLS, target) {
|
||||
!builtin_testdata:contains(INSTALLS, target) {
|
||||
# Install testdata and helpers as well, but only if we're actually installing the test.
|
||||
#
|
||||
# Testdata is installed relative to the directory containing the testcase
|
||||
@ -175,6 +175,20 @@ contains(INSTALLS, target) {
|
||||
}
|
||||
}
|
||||
|
||||
builtin_testdata {
|
||||
ALL_TESTDATA = $$TESTDATA $$GENERATED_TESTDATA
|
||||
# RESOURCES does not support wildcards (for good reasons)
|
||||
for(td, ALL_TESTDATA): \
|
||||
testdata.files += $$files($$absolute_path($$td, $$_PRO_FILE_PWD_))
|
||||
!isEmpty(testdata.files) {
|
||||
testdata.base = $$_PRO_FILE_PWD_
|
||||
RESOURCES += testdata
|
||||
}
|
||||
|
||||
!isEmpty(TEST_HELPER_INSTALLS): \
|
||||
error("This platform does not support tests which require helpers.")
|
||||
}
|
||||
|
||||
macx-xcode:bundle:isEmpty(QMAKE_BUNDLE_EXTENSION) {
|
||||
QMAKE_PBX_PRODUCT_TYPE = com.apple.product-type.bundle.unit-test
|
||||
QMAKE_PBX_BUNDLE_TYPE = wrapper.cfbundle
|
||||
|
@ -2408,7 +2408,6 @@
|
||||
\row \li .file \li Specify the subproject \c pro file explicitly. Cannot be
|
||||
used in conjunction with \c .subdir modifier.
|
||||
\row \li .depends \li This subproject depends on specified subproject.
|
||||
Available only on platforms that use makefiles.
|
||||
\row \li .makefile \li The makefile of subproject.
|
||||
Available only on platforms that use makefiles.
|
||||
\row \li .target \li Base string used for makefile targets related to this
|
||||
|
@ -388,6 +388,121 @@ QFileInfo QMakeSourceFileInfo::findFileInfo(const QMakeLocalFileName &dep)
|
||||
return QFileInfo(dep.real());
|
||||
}
|
||||
|
||||
static int skipEscapedLineEnds(const char *buffer, int buffer_len, int offset, int *lines)
|
||||
{
|
||||
// Join physical lines to make logical lines, as in the C preprocessor
|
||||
while (offset + 1 < buffer_len
|
||||
&& buffer[offset] == '\\'
|
||||
&& qmake_endOfLine(buffer[offset + 1])) {
|
||||
offset += 2;
|
||||
++*lines;
|
||||
if (offset < buffer_len
|
||||
&& buffer[offset - 1] == '\r'
|
||||
&& buffer[offset] == '\n') // CRLF
|
||||
offset++;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
static bool matchWhileUnsplitting(const char *buffer, int buffer_len, int start,
|
||||
const char *needle, int needle_len,
|
||||
int *matchlen, int *lines)
|
||||
{
|
||||
int x = start;
|
||||
for (int n = 0; n < needle_len && x < buffer_len;
|
||||
n++, x = skipEscapedLineEnds(buffer, buffer_len, x + 1, lines)) {
|
||||
if (buffer[x] != needle[n])
|
||||
return false;
|
||||
}
|
||||
// That also skipped any remaining BSNLs immediately after the match.
|
||||
|
||||
// Tell caller how long the match was:
|
||||
*matchlen = x - start;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Advance from an opening quote at buffer[offset] to the matching close quote. */
|
||||
static int scanPastString(char *buffer, int buffer_len, int offset, int *lines)
|
||||
{
|
||||
// It might be a C++11 raw string.
|
||||
bool israw = false;
|
||||
if (buffer[offset] == '"' && offset > 0) {
|
||||
int explore = offset - 1;
|
||||
while (explore > 0 && buffer[explore] != 'R') {
|
||||
if (buffer[explore] == '8' || buffer[explore] == 'u' || buffer[explore] == 'U') {
|
||||
explore--;
|
||||
} else if (explore > 1 && qmake_endOfLine(buffer[explore])
|
||||
&& buffer[explore - 1] == '\\') {
|
||||
explore -= 2;
|
||||
} else if (explore > 2 && buffer[explore] == '\n'
|
||||
&& buffer[explore - 1] == '\r'
|
||||
&& buffer[explore - 2] == '\\') {
|
||||
explore -= 3;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
israw = (buffer[explore] == 'R');
|
||||
}
|
||||
|
||||
if (israw) {
|
||||
#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), lines)
|
||||
|
||||
offset = SKIP_BSNL(offset + 1);
|
||||
const char *const delim = buffer + offset;
|
||||
int clean = offset;
|
||||
while (offset < buffer_len && buffer[offset] != '(') {
|
||||
if (clean < offset)
|
||||
buffer[clean++] = buffer[offset];
|
||||
else
|
||||
clean++;
|
||||
|
||||
offset = SKIP_BSNL(offset + 1);
|
||||
}
|
||||
/*
|
||||
Not checking correctness (trust real compiler to do that):
|
||||
- no controls, spaces, '(', ')', '\\' or (presumably) '"' in delim;
|
||||
- at most 16 bytes in delim
|
||||
|
||||
Raw strings are surely defined after phase 2, when BSNLs are resolved;
|
||||
so the delimiter's exclusion of '\\' and space (including newlines)
|
||||
applies too late to save us the need to cope with BSNLs in it.
|
||||
*/
|
||||
|
||||
const int delimlen = buffer + clean - delim;
|
||||
int matchlen = delimlen, extralines = 0;
|
||||
while ((offset = SKIP_BSNL(offset + 1)) < buffer_len
|
||||
&& (buffer[offset] != ')'
|
||||
|| (delimlen > 0 &&
|
||||
!matchWhileUnsplitting(buffer, buffer_len,
|
||||
offset + 1, delim, delimlen,
|
||||
&matchlen, &extralines))
|
||||
|| buffer[offset + 1 + matchlen] != '"')) {
|
||||
// skip, but keep track of lines
|
||||
if (qmake_endOfLine(buffer[offset]))
|
||||
++*lines;
|
||||
extralines = 0;
|
||||
}
|
||||
*lines += extralines; // from the match
|
||||
// buffer[offset] is ')'
|
||||
offset += 1 + matchlen; // 1 for ')', then delim
|
||||
// buffer[offset] is '"'
|
||||
|
||||
#undef SKIP_BSNL
|
||||
} else { // Traditional string or char literal:
|
||||
const char term = buffer[offset];
|
||||
while (++offset < buffer_len && buffer[offset] != term) {
|
||||
if (buffer[offset] == '\\')
|
||||
++offset;
|
||||
else if (qmake_endOfLine(buffer[offset]))
|
||||
++*lines;
|
||||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
bool QMakeSourceFileInfo::findDeps(SourceFile *file)
|
||||
{
|
||||
if(file->dep_checked || file->type == TYPE_UNKNOWN)
|
||||
@ -426,6 +541,18 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
|
||||
file->deps = new SourceDependChildren;
|
||||
|
||||
int line_count = 1;
|
||||
enum {
|
||||
/*
|
||||
States of C preprocessing (for TYPE_C only), after backslash-newline
|
||||
elimination and skipping comments and spaces (i.e. in ANSI X3.159-1989
|
||||
section 2.1.1.2's phase 4). We're about to study buffer[x] to decide
|
||||
on which transition to do.
|
||||
*/
|
||||
AtStart, // start of logical line; a # may start a preprocessor directive
|
||||
HadHash, // saw a # at start, looking for preprocessor keyword
|
||||
WantName, // saw #include or #import, waiting for name
|
||||
InCode // after directive, parsing non-#include directive or in actual code
|
||||
} cpp_state = AtStart;
|
||||
|
||||
for(int x = 0; x < buffer_len; ++x) {
|
||||
bool try_local = true;
|
||||
@ -505,118 +632,164 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
|
||||
++line_count;
|
||||
} else if(file->type == QMakeSourceFileInfo::TYPE_QRC) {
|
||||
} else if(file->type == QMakeSourceFileInfo::TYPE_C) {
|
||||
for(int beginning=1; x < buffer_len; ++x) {
|
||||
// We've studied all buffer[i] for i < x
|
||||
for (; x < buffer_len; ++x) {
|
||||
// How to handle backslash-newline (BSNL) pairs:
|
||||
#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count)
|
||||
|
||||
// Seek code or directive, skipping comments and space:
|
||||
for(; x < buffer_len; ++x) {
|
||||
x = SKIP_BSNL(x);
|
||||
if (buffer[x] == ' ' || buffer[x] == '\t') {
|
||||
// keep going
|
||||
} else if (buffer[x] == '/' && x + 1 < buffer_len &&
|
||||
(buffer[x + 1] == '/' || buffer[x + 1] == '*')) {
|
||||
++x;
|
||||
if (buffer[x] == '/') { // C++-style comment
|
||||
for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip
|
||||
beginning = 1;
|
||||
} else { // C-style comment
|
||||
} else if (buffer[x] == '/') {
|
||||
int extralines = 0;
|
||||
int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
|
||||
if (buffer[y] == '/') { // C++-style comment
|
||||
line_count += extralines;
|
||||
x = SKIP_BSNL(y + 1);
|
||||
while (x < buffer_len && !qmake_endOfLine(buffer[x]))
|
||||
x = SKIP_BSNL(x + 1); // skip
|
||||
|
||||
cpp_state = AtStart;
|
||||
++line_count;
|
||||
} else if (buffer[y] == '*') { // C-style comment
|
||||
line_count += extralines;
|
||||
x = y;
|
||||
while (++x < buffer_len) {
|
||||
x = SKIP_BSNL(x);
|
||||
if (buffer[x] == '*') {
|
||||
if (x + 1 < buffer_len && buffer[x + 1] == '/') {
|
||||
++x; // skip '*'; for loop skips '/'.
|
||||
extralines = 0;
|
||||
y = skipEscapedLineEnds(buffer, buffer_len,
|
||||
x + 1, &extralines);
|
||||
if (y < buffer_len && buffer[y] == '/') {
|
||||
line_count += extralines;
|
||||
x = y; // for loop shall step past this
|
||||
break;
|
||||
}
|
||||
} else if (qmake_endOfLine(buffer[x])) {
|
||||
++line_count;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// buffer[x] is the division operator
|
||||
break;
|
||||
}
|
||||
} else if (qmake_endOfLine(buffer[x])) {
|
||||
++line_count;
|
||||
beginning = 1;
|
||||
cpp_state = AtStart;
|
||||
} else {
|
||||
/* Drop out of phases 1, 2, 3, into phase 4 */
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Phase 4 study of buffer[x]:
|
||||
|
||||
if(x >= buffer_len)
|
||||
break;
|
||||
|
||||
// preprocessor directive
|
||||
if (beginning && buffer[x] == '#') {
|
||||
// Advance to start of preprocessing directive
|
||||
while (++x < buffer_len
|
||||
&& (buffer[x] == ' ' || buffer[x] == '\t')) {} // skip
|
||||
switch (cpp_state) {
|
||||
case HadHash:
|
||||
{
|
||||
// Read keyword; buffer[x] starts first preprocessing token after #
|
||||
const char *const keyword = buffer + x;
|
||||
int clean = x;
|
||||
while (x < buffer_len && buffer[x] >= 'a' && buffer[x] <= 'z') {
|
||||
// skip over keyword, consolidating it if it contains BSNLs
|
||||
// (see WantName's similar code consolidating inc, below)
|
||||
if (clean < x)
|
||||
buffer[clean++] = buffer[x];
|
||||
else
|
||||
clean++;
|
||||
|
||||
if (qmake_endOfLine(buffer[x])) {
|
||||
++line_count;
|
||||
beginning = 1;
|
||||
continue;
|
||||
x = SKIP_BSNL(x + 1);
|
||||
}
|
||||
const int keyword_len = buffer + clean - keyword;
|
||||
x--; // Still need to study buffer[x] next time round for loop.
|
||||
|
||||
cpp_state =
|
||||
((keyword_len == 7 && !strncmp(keyword, "include", 7)) // C & Obj-C
|
||||
|| (keyword_len == 6 && !strncmp(keyword, "import", 6))) // Obj-C
|
||||
? WantName : InCode;
|
||||
break;
|
||||
}
|
||||
|
||||
// quoted strings
|
||||
if (buffer[x] == '\'' || buffer[x] == '"') {
|
||||
const char term = buffer[x];
|
||||
while (++x < buffer_len) {
|
||||
if (buffer[x] == term) {
|
||||
++x;
|
||||
break;
|
||||
} else if (buffer[x] == '\\') {
|
||||
++x;
|
||||
} else if (qmake_endOfLine(buffer[x])) {
|
||||
++line_count;
|
||||
}
|
||||
case WantName:
|
||||
{
|
||||
char term = buffer[x];
|
||||
if (term == '<') {
|
||||
try_local = false;
|
||||
term = '>';
|
||||
} else if (term != '"') {
|
||||
/*
|
||||
Possibly malformed, but this may be something like:
|
||||
#include IDENTIFIER
|
||||
which does work, if #define IDENTIFIER "filename" is
|
||||
in effect. This is beyond this noddy preprocessor's
|
||||
powers of tracking. So give up and resume searching
|
||||
for a directive. We haven't made sense of buffer[x],
|
||||
so back up to ensure we do study it (now as code) next
|
||||
time round the loop.
|
||||
*/
|
||||
x--;
|
||||
cpp_state = InCode;
|
||||
continue;
|
||||
}
|
||||
|
||||
x = SKIP_BSNL(x + 1);
|
||||
inc = buffer + x;
|
||||
int clean = x; // offset if we need to clear \-newlines
|
||||
for (; x < buffer_len && buffer[x] != term; x = SKIP_BSNL(x + 1)) {
|
||||
if (qmake_endOfLine(buffer[x])) { // malformed
|
||||
cpp_state = AtStart;
|
||||
++line_count;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
If we do skip any BSNLs, we need to consolidate the
|
||||
surviving text by copying to lower indices. For that
|
||||
to be possible, we also have to keep 'clean' advanced
|
||||
in step with x even when we've yet to see any BSNLs.
|
||||
*/
|
||||
if (clean < x)
|
||||
buffer[clean++] = buffer[x];
|
||||
else
|
||||
clean++;
|
||||
}
|
||||
if (cpp_state == WantName)
|
||||
buffer[clean] = '\0';
|
||||
else // i.e. malformed
|
||||
inc = 0;
|
||||
|
||||
cpp_state = InCode; // hereafter
|
||||
break;
|
||||
}
|
||||
beginning = 0;
|
||||
|
||||
case AtStart:
|
||||
// Preprocessor directive?
|
||||
if (buffer[x] == '#') {
|
||||
cpp_state = HadHash;
|
||||
break;
|
||||
}
|
||||
cpp_state = InCode;
|
||||
// ... and fall through to handle buffer[x] as such.
|
||||
case InCode:
|
||||
// matching quotes (string literals and character literals)
|
||||
if (buffer[x] == '\'' || buffer[x] == '"') {
|
||||
x = scanPastString(buffer, buffer_len, x, &line_count);
|
||||
// for loop's ++x shall step over the closing quote.
|
||||
}
|
||||
// else: buffer[x] is just some code; move on.
|
||||
break;
|
||||
}
|
||||
|
||||
if (inc) // We were in WantName and found a name.
|
||||
break;
|
||||
#undef SKIP_BSNL
|
||||
}
|
||||
if(x >= buffer_len)
|
||||
break;
|
||||
|
||||
// Got a preprocessor directive
|
||||
const char *const keyword = buffer + x;
|
||||
for (;
|
||||
x < buffer_len && buffer[x] >= 'a' && buffer[x] <= 'z';
|
||||
x++) {} // skip over identifier
|
||||
int keyword_len = buffer + x - keyword;
|
||||
for (;
|
||||
x < buffer_len && (buffer[x] == ' ' || buffer[x] == '\t');
|
||||
x++) {} // skip spaces after keyword
|
||||
|
||||
/* Keyword with nothing after it, e.g. #endif: not interesting. */
|
||||
if (qmake_endOfLine(buffer[x]))
|
||||
keyword_len = 0;
|
||||
|
||||
if((keyword_len == 7 && !strncmp(keyword, "include", 7)) // C & Obj-C
|
||||
|| (keyword_len == 6 && !strncmp(keyword, "import", 6))) { // Obj-C
|
||||
char term = buffer[x];
|
||||
if(term == '<') {
|
||||
try_local = false;
|
||||
term = '>';
|
||||
} else if(term != '"') { //wtf?
|
||||
continue;
|
||||
}
|
||||
x++;
|
||||
inc = buffer + x;
|
||||
for (;
|
||||
buffer[x] != term && !qmake_endOfLine(buffer[x]);
|
||||
++x) {} // skip until end of include name
|
||||
buffer[x] = '\0';
|
||||
} else if (buffer[x] == '\'' || buffer[x] == '"') {
|
||||
const char term = buffer[x++];
|
||||
while(x < buffer_len) {
|
||||
if (buffer[x] == term)
|
||||
break;
|
||||
if (buffer[x] == '\\') {
|
||||
x+=2;
|
||||
} else {
|
||||
if (qmake_endOfLine(buffer[x]))
|
||||
++line_count;
|
||||
++x;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
--x;
|
||||
}
|
||||
}
|
||||
|
||||
if(inc) {
|
||||
@ -699,7 +872,7 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
|
||||
files_changed = true;
|
||||
file->moc_checked = true;
|
||||
|
||||
int buffer_len;
|
||||
int buffer_len = 0;
|
||||
char *buffer = 0;
|
||||
{
|
||||
struct stat fst;
|
||||
@ -717,42 +890,56 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
|
||||
return false; //shouldn't happen
|
||||
}
|
||||
buffer = getBuffer(fst.st_size);
|
||||
for(int have_read = buffer_len = 0;
|
||||
(have_read = QT_READ(fd, buffer + buffer_len, fst.st_size - buffer_len));
|
||||
buffer_len += have_read) ;
|
||||
while (int have_read = QT_READ(fd, buffer + buffer_len, fst.st_size - buffer_len))
|
||||
buffer_len += have_read;
|
||||
|
||||
QT_CLOSE(fd);
|
||||
}
|
||||
|
||||
debug_msg(2, "findMocs: %s", file->file.local().toLatin1().constData());
|
||||
int line_count = 1;
|
||||
bool ignore_qobject = false, ignore_qgadget = false;
|
||||
bool ignore[2] = { false, false }; // [0] for Q_OBJECT, [1] for Q_GADGET
|
||||
/* qmake ignore Q_GADGET */
|
||||
/* qmake ignore Q_OBJECT */
|
||||
for(int x = 0; x < buffer_len; x++) {
|
||||
#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count)
|
||||
x = SKIP_BSNL(x);
|
||||
if (buffer[x] == '/') {
|
||||
++x;
|
||||
if(buffer_len >= x) {
|
||||
if (buffer[x] == '/') { // C++-style comment
|
||||
for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip
|
||||
} else if (buffer[x] == '*') { // C-style comment
|
||||
for(++x; x < buffer_len; ++x) {
|
||||
int extralines = 0;
|
||||
int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
|
||||
if (buffer_len > y) {
|
||||
// If comment, advance to the character that ends it:
|
||||
if (buffer[y] == '/') { // C++-style comment
|
||||
line_count += extralines;
|
||||
x = y;
|
||||
do {
|
||||
x = SKIP_BSNL(x + 1);
|
||||
} while (x < buffer_len && !qmake_endOfLine(buffer[x]));
|
||||
|
||||
} else if (buffer[y] == '*') { // C-style comment
|
||||
line_count += extralines;
|
||||
x = SKIP_BSNL(y + 1);
|
||||
for (; x < buffer_len; x = SKIP_BSNL(x + 1)) {
|
||||
if (buffer[x] == 't' || buffer[x] == 'q') { // ignore
|
||||
if(buffer_len >= (x + 20) &&
|
||||
!strncmp(buffer + x + 1, "make ignore Q_OBJECT", 20)) {
|
||||
debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_OBJECT\"",
|
||||
file->file.real().toLatin1().constData(), line_count);
|
||||
x += 20;
|
||||
ignore_qobject = true;
|
||||
ignore[0] = true;
|
||||
} else if(buffer_len >= (x + 20) &&
|
||||
!strncmp(buffer + x + 1, "make ignore Q_GADGET", 20)) {
|
||||
debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_GADGET\"",
|
||||
file->file.real().toLatin1().constData(), line_count);
|
||||
x += 20;
|
||||
ignore_qgadget = true;
|
||||
ignore[1] = true;
|
||||
}
|
||||
} else if (buffer[x] == '*') {
|
||||
if (buffer_len >= x + 1 && buffer[x + 1] == '/') {
|
||||
++x;
|
||||
extralines = 0;
|
||||
y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
|
||||
if (buffer_len > y && buffer[y] == '/') {
|
||||
line_count += extralines;
|
||||
x = y;
|
||||
break;
|
||||
}
|
||||
} else if (Option::debug_level && qmake_endOfLine(buffer[x])) {
|
||||
@ -760,56 +947,44 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
|
||||
}
|
||||
}
|
||||
}
|
||||
// else: don't update x, buffer[x] is just the division operator.
|
||||
}
|
||||
} else if (buffer[x] == '\'' || buffer[x] == '"') {
|
||||
const char term = buffer[x++];
|
||||
while(x < buffer_len) {
|
||||
if (buffer[x] == term)
|
||||
break;
|
||||
if (buffer[x] == '\\') {
|
||||
x+=2;
|
||||
} else {
|
||||
if (qmake_endOfLine(buffer[x]))
|
||||
++line_count;
|
||||
++x;
|
||||
}
|
||||
}
|
||||
x = scanPastString(buffer, buffer_len, x, &line_count);
|
||||
// Leaves us on closing quote; for loop's x++ steps us past it.
|
||||
}
|
||||
if (Option::debug_level && qmake_endOfLine(buffer[x]))
|
||||
|
||||
if (x < buffer_len && Option::debug_level && qmake_endOfLine(buffer[x]))
|
||||
++line_count;
|
||||
if (buffer_len > x + 2 && buffer[x + 1] == 'Q' &&
|
||||
buffer[x + 2] == '_' && !isCWordChar(buffer[x])) {
|
||||
++x;
|
||||
int match = 0;
|
||||
static const char *interesting[] = { "OBJECT", "GADGET" };
|
||||
for (int interest = 0, m1, m2; interest < 2; ++interest) {
|
||||
if(interest == 0 && ignore_qobject)
|
||||
continue;
|
||||
else if(interest == 1 && ignore_qgadget)
|
||||
continue;
|
||||
for (m1 = 0, m2 = 0; interesting[interest][m1]; ++m1) {
|
||||
if (interesting[interest][m1] != buffer[x + 2 + m1]) {
|
||||
m2 = -1;
|
||||
break;
|
||||
if (buffer_len > x + 8 && !isCWordChar(buffer[x])) {
|
||||
int morelines = 0;
|
||||
int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &morelines);
|
||||
if (buffer[y] == 'Q') {
|
||||
static const char interesting[][9] = { "Q_OBJECT", "Q_GADGET" };
|
||||
for (int interest = 0; interest < 2; ++interest) {
|
||||
if (ignore[interest])
|
||||
continue;
|
||||
|
||||
int matchlen = 0, extralines = 0;
|
||||
if (matchWhileUnsplitting(buffer, buffer_len, y,
|
||||
interesting[interest],
|
||||
strlen(interesting[interest]),
|
||||
&matchlen, &extralines)
|
||||
&& y + matchlen < buffer_len
|
||||
&& !isCWordChar(buffer[y + matchlen])) {
|
||||
if (Option::debug_level) {
|
||||
buffer[y + matchlen] = '\0';
|
||||
debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s",
|
||||
file->file.real().toLatin1().constData(),
|
||||
line_count + morelines, buffer + y);
|
||||
}
|
||||
file->mocable = true;
|
||||
return true;
|
||||
}
|
||||
++m2;
|
||||
}
|
||||
if(m1 == m2) {
|
||||
match = m2 + 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match && !isCWordChar(buffer[x + match])) {
|
||||
if (Option::debug_level) {
|
||||
buffer[x + match] = '\0';
|
||||
debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s",
|
||||
file->file.real().toLatin1().constData(),
|
||||
line_count, buffer + x);
|
||||
}
|
||||
file->mocable = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#undef SKIP_BSNL
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -142,18 +142,8 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
|
||||
|
||||
const bool isPhone = project->isActiveConfig(QStringLiteral("winphone"));
|
||||
#ifdef Q_OS_WIN
|
||||
QString regKeyPrefix;
|
||||
#if !defined(Q_OS_WIN64) && _WIN32_WINNT >= 0x0501
|
||||
BOOL isWow64;
|
||||
IsWow64Process(GetCurrentProcess(), &isWow64);
|
||||
if (!isWow64)
|
||||
regKeyPrefix = QStringLiteral("Software\\");
|
||||
else
|
||||
#endif
|
||||
regKeyPrefix = QStringLiteral("Software\\Wow6432Node\\");
|
||||
|
||||
QString regKey = regKeyPrefix + QStringLiteral("Microsoft\\VisualStudio\\") + msvcVer + ("\\Setup\\VC\\ProductDir");
|
||||
const QString vcInstallDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey);
|
||||
QString regKey = QStringLiteral("Software\\Microsoft\\VisualStudio\\") + msvcVer + ("\\Setup\\VC\\ProductDir");
|
||||
const QString vcInstallDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey, KEY_WOW64_32KEY);
|
||||
if (vcInstallDir.isEmpty()) {
|
||||
fprintf(stderr, "Failed to find the Visual Studio installation directory.\n");
|
||||
return false;
|
||||
@ -161,13 +151,13 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
|
||||
|
||||
QString windowsPath;
|
||||
if (isPhone) {
|
||||
windowsPath = "Microsoft\\Microsoft SDKs\\WindowsPhoneApp\\v";
|
||||
windowsPath = "Software\\Microsoft\\Microsoft SDKs\\WindowsPhoneApp\\v";
|
||||
} else {
|
||||
windowsPath = "Microsoft\\Microsoft SDKs\\Windows\\v";
|
||||
windowsPath = "Software\\Microsoft\\Microsoft SDKs\\Windows\\v";
|
||||
}
|
||||
|
||||
regKey = regKeyPrefix + windowsPath + winsdkVer + QStringLiteral("\\InstallationFolder");
|
||||
const QString kitDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey);
|
||||
regKey = windowsPath + winsdkVer + QStringLiteral("\\InstallationFolder");
|
||||
const QString kitDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey, KEY_WOW64_32KEY);
|
||||
if (kitDir.isEmpty()) {
|
||||
fprintf(stderr, "Failed to find the Windows Kit installation directory.\n");
|
||||
return false;
|
||||
|
@ -70,21 +70,6 @@ struct DotNetCombo {
|
||||
const char *versionStr;
|
||||
const char *regKey;
|
||||
} dotNetCombo[] = {
|
||||
#ifdef Q_OS_WIN64
|
||||
{NET2015, "MSVC.NET 2015 (14.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"},
|
||||
{NET2013, "MSVC.NET 2013 (12.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"},
|
||||
{NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"},
|
||||
{NET2012, "MSVC.NET 2012 (11.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\11.0\\Setup\\VC\\ProductDir"},
|
||||
{NET2012, "MSVC.NET 2012 Express Edition (11.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\11.0\\Setup\\VC\\ProductDir"},
|
||||
{NET2010, "MSVC.NET 2010 (10.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\10.0\\Setup\\VC\\ProductDir"},
|
||||
{NET2010, "MSVC.NET 2010 Express Edition (10.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\10.0\\Setup\\VC\\ProductDir"},
|
||||
{NET2008, "MSVC.NET 2008 (9.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\9.0\\Setup\\VC\\ProductDir"},
|
||||
{NET2008, "MSVC.NET 2008 Express Edition (9.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\9.0\\Setup\\VC\\ProductDir"},
|
||||
{NET2005, "MSVC.NET 2005 (8.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"},
|
||||
{NET2005, "MSVC.NET 2005 Express Edition (8.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\8.0\\Setup\\VC\\ProductDir"},
|
||||
{NET2003, "MSVC.NET 2003 (7.1)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"},
|
||||
{NET2002, "MSVC.NET 2002 (7.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"},
|
||||
#else
|
||||
{NET2015, "MSVC.NET 2015 (14.0)", "Software\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"},
|
||||
{NET2013, "MSVC.NET 2013 (12.0)", "Software\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"},
|
||||
{NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"},
|
||||
@ -98,7 +83,6 @@ struct DotNetCombo {
|
||||
{NET2005, "MSVC.NET 2005 Express Edition (8.0)", "Software\\Microsoft\\VCExpress\\8.0\\Setup\\VC\\ProductDir"},
|
||||
{NET2003, "MSVC.NET 2003 (7.1)", "Software\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"},
|
||||
{NET2002, "MSVC.NET 2002 (7.0)", "Software\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"},
|
||||
#endif
|
||||
{NETUnknown, "", ""},
|
||||
};
|
||||
|
||||
@ -125,7 +109,8 @@ DotNET which_dotnet_version(const QByteArray &preferredVersion = QByteArray())
|
||||
int installed = 0;
|
||||
int i = 0;
|
||||
for(; dotNetCombo[i].version; ++i) {
|
||||
QString path = qt_readRegistryKey(HKEY_LOCAL_MACHINE, dotNetCombo[i].regKey);
|
||||
QString path = qt_readRegistryKey(HKEY_LOCAL_MACHINE, dotNetCombo[i].regKey,
|
||||
KEY_WOW64_32KEY);
|
||||
if (!path.isEmpty() && installPaths.value(dotNetCombo[i].version) != path) {
|
||||
lowestInstalledVersion = &dotNetCombo[i];
|
||||
installPaths.insert(lowestInstalledVersion->version, path);
|
||||
|
@ -904,6 +904,7 @@ public class QtActivityDelegate
|
||||
public void onDestroy()
|
||||
{
|
||||
if (m_quitApp) {
|
||||
QtNative.terminateQt();
|
||||
if (m_debuggerProcess != null)
|
||||
m_debuggerProcess.destroy();
|
||||
System.exit(0);// FIXME remove it or find a better way
|
||||
|
@ -294,7 +294,12 @@ public class QtNative
|
||||
|
||||
private static void quitApp()
|
||||
{
|
||||
m_activity.finish();
|
||||
runAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
m_activity.finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//@ANDROID-9
|
||||
|
@ -92,6 +92,7 @@ QT_END_NAMESPACE
|
||||
#include <private/qthread_p.h>
|
||||
#include <qfile.h>
|
||||
#include <qfileinfo.h>
|
||||
#include <qdir.h>
|
||||
#include <qlist.h>
|
||||
#include <qmutex.h>
|
||||
#include <qsemaphore.h>
|
||||
@ -362,11 +363,14 @@ void QProcessPrivate::startProcess()
|
||||
static QBasicMutex cfbundleMutex;
|
||||
QMutexLocker lock(&cfbundleMutex);
|
||||
QCFType<CFBundleRef> bundle = CFBundleCreate(0, url);
|
||||
url = CFBundleCopyExecutableURL(bundle);
|
||||
// 'executableURL' can be either relative or absolute ...
|
||||
QCFType<CFURLRef> executableURL = CFBundleCopyExecutableURL(bundle);
|
||||
// not to depend on caching - make sure it's always absolute.
|
||||
url = CFURLCopyAbsoluteURL(executableURL);
|
||||
}
|
||||
if (url) {
|
||||
QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
|
||||
encodedProgramName += "/Contents/MacOS/" + QCFString::toQString(str).toUtf8();
|
||||
const QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
|
||||
encodedProgramName += (QDir::separator() + QDir(program).relativeFilePath(QCFString::toQString(str))).toUtf8();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -693,6 +693,11 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*! \typedef QJsonObject::iterator::pointer
|
||||
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*! \fn QJsonObject::iterator::iterator()
|
||||
|
||||
Constructs an uninitialized iterator.
|
||||
@ -895,6 +900,11 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*! \typedef QJsonObject::const_iterator::pointer
|
||||
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*! \fn QJsonObject::const_iterator::const_iterator()
|
||||
|
||||
Constructs an uninitialized iterator.
|
||||
|
@ -104,6 +104,7 @@ public:
|
||||
typedef int difference_type;
|
||||
typedef QJsonValue value_type;
|
||||
typedef QJsonValueRef reference;
|
||||
typedef QJsonValuePtr pointer;
|
||||
|
||||
Q_DECL_CONSTEXPR inline iterator() : o(Q_NULLPTR), i(0) {}
|
||||
Q_DECL_CONSTEXPR inline iterator(QJsonObject *obj, int index) : o(obj), i(index) {}
|
||||
@ -146,6 +147,7 @@ public:
|
||||
typedef int difference_type;
|
||||
typedef QJsonValue value_type;
|
||||
typedef QJsonValue reference;
|
||||
typedef QJsonValuePtr pointer;
|
||||
|
||||
Q_DECL_CONSTEXPR inline const_iterator() : o(Q_NULLPTR), i(0) {}
|
||||
Q_DECL_CONSTEXPR inline const_iterator(const QJsonObject *obj, int index)
|
||||
|
@ -201,14 +201,16 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
|
||||
{
|
||||
Q_D(QEventDispatcherWinRT);
|
||||
|
||||
DWORD waitTime = 0;
|
||||
do {
|
||||
// Additional user events have to be handled before timer events, but the function may not
|
||||
// return yet.
|
||||
const bool userEventsSent = sendPostedEvents(flags);
|
||||
|
||||
emit aboutToBlock();
|
||||
const QVector<HANDLE> timerHandles = d->timerIdToHandle.values().toVector();
|
||||
DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, 1, TRUE);
|
||||
if (waitTime)
|
||||
emit aboutToBlock();
|
||||
DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, waitTime, TRUE);
|
||||
if (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0 + timerHandles.count()) {
|
||||
const HANDLE handle = timerHandles.value(waitResult - WAIT_OBJECT_0);
|
||||
ResetEvent(handle);
|
||||
@ -231,6 +233,13 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
|
||||
|
||||
if (userEventsSent)
|
||||
return true;
|
||||
|
||||
// We cannot wait infinitely like on other platforms, as
|
||||
// WaitForMultipleObjectsEx might not return.
|
||||
// For instance win32 uses MsgWaitForMultipleObjects to hook
|
||||
// into the native event loop, while WinRT handles those
|
||||
// via callbacks.
|
||||
waitTime = 1;
|
||||
} while (flags & QEventLoop::WaitForMoreEvents);
|
||||
return false;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ void QSharedMemoryPrivate::setErrorString(QLatin1String function)
|
||||
errorString = QSharedMemory::tr("%1: already exists").arg(function);
|
||||
break;
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
#ifdef Q_OS_WINCE
|
||||
#if defined(Q_OS_WINCE) || (defined(Q_OS_WINRT) && _MSC_VER < 1900)
|
||||
// This happens on CE only if no file is present as CreateFileMappingW
|
||||
// bails out with this error code
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
@ -101,7 +101,11 @@ HANDLE QSharedMemoryPrivate::handle()
|
||||
Q_UNIMPLEMENTED();
|
||||
hand = 0;
|
||||
#elif defined(Q_OS_WINRT)
|
||||
#if _MSC_VER >= 1900
|
||||
hand = OpenFileMappingFromApp(FILE_MAP_ALL_ACCESS, FALSE, reinterpret_cast<PCWSTR>(nativeKey.utf16()));
|
||||
#else
|
||||
hand = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, (PCWSTR)nativeKey.utf16());
|
||||
#endif
|
||||
#elif defined(Q_OS_WINCE)
|
||||
// This works for opening a mapping too, but always opens it with read/write access in
|
||||
// attach as it seems.
|
||||
|
@ -772,7 +772,7 @@ namespace QtPrivate {
|
||||
QVariantHash l;
|
||||
l.reserve(iter.size());
|
||||
for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
|
||||
l.insert(it.key().toString(), it.value());
|
||||
l.insertMulti(it.key().toString(), it.value());
|
||||
return l;
|
||||
}
|
||||
return QVariantValueHelper<QVariantHash>::invoke(v);
|
||||
@ -788,7 +788,7 @@ namespace QtPrivate {
|
||||
QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
|
||||
QVariantMap l;
|
||||
for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
|
||||
l.insert(it.key().toString(), it.value());
|
||||
l.insertMulti(it.key().toString(), it.value());
|
||||
return l;
|
||||
}
|
||||
return QVariantValueHelper<QVariantMap>::invoke(v);
|
||||
|
@ -124,7 +124,8 @@ bool QLibraryPrivate::load_sys()
|
||||
SetErrorMode(oldmode);
|
||||
#endif
|
||||
if (!pHnd) {
|
||||
errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qt_error_string());
|
||||
errorString = QLibrary::tr("Cannot load library %1: %2").arg(
|
||||
QDir::toNativeSeparators(fileName)).arg(qt_error_string());
|
||||
} else {
|
||||
// Query the actual name of the library that was loaded
|
||||
errorString.clear();
|
||||
@ -148,7 +149,8 @@ bool QLibraryPrivate::load_sys()
|
||||
bool QLibraryPrivate::unload_sys()
|
||||
{
|
||||
if (!FreeLibrary(pHnd)) {
|
||||
errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qt_error_string());
|
||||
errorString = QLibrary::tr("Cannot unload library %1: %2").arg(
|
||||
QDir::toNativeSeparators(fileName)).arg(qt_error_string());
|
||||
return false;
|
||||
}
|
||||
errorString.clear();
|
||||
@ -164,7 +166,8 @@ QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
|
||||
#endif
|
||||
if (!address) {
|
||||
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
|
||||
QString::fromLatin1(symbol)).arg(fileName).arg(qt_error_string());
|
||||
QString::fromLatin1(symbol)).arg(
|
||||
QDir::toNativeSeparators(fileName)).arg(qt_error_string());
|
||||
} else {
|
||||
errorString.clear();
|
||||
}
|
||||
|
@ -500,7 +500,7 @@ private:
|
||||
template <class X>
|
||||
inline void enableSharedFromThis(const QEnableSharedFromThis<X> *ptr)
|
||||
{
|
||||
ptr->initializeFromSharedPointer(*this);
|
||||
ptr->initializeFromSharedPointer(constCast<typename QtPrivate::remove_cv<T>::type>());
|
||||
}
|
||||
|
||||
inline void enableSharedFromThis(...) {}
|
||||
|
@ -1819,6 +1819,17 @@ QString &QString::operator=(const QString &other) Q_DECL_NOTHROW
|
||||
|
||||
Assigns the Latin-1 string \a str to this string.
|
||||
*/
|
||||
QString &QString::operator=(QLatin1String other)
|
||||
{
|
||||
if (isDetached() && other.size() <= capacity()) { // assumes d->alloc == 0 → !isDetached() (sharedNull)
|
||||
d->size = other.size();
|
||||
d->data()[other.size()] = 0;
|
||||
qt_from_latin1(d->data(), other.latin1(), other.size());
|
||||
} else {
|
||||
*this = fromLatin1(other.latin1(), other.size());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*! \fn QString &QString::operator=(const QByteArray &ba)
|
||||
|
||||
@ -1869,7 +1880,16 @@ QString &QString::operator=(const QString &other) Q_DECL_NOTHROW
|
||||
*/
|
||||
QString &QString::operator=(QChar ch)
|
||||
{
|
||||
return operator=(QString(ch));
|
||||
if (isDetached() && capacity() >= 1) { // assumes d->alloc == 0 → !isDetached() (sharedNull)
|
||||
// re-use existing capacity:
|
||||
ushort *dat = d->data();
|
||||
dat[0] = ch.unicode();
|
||||
dat[1] = 0;
|
||||
d->size = 1;
|
||||
} else {
|
||||
operator=(QString(ch));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -5667,7 +5687,7 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const
|
||||
*/
|
||||
|
||||
namespace QUnicodeTables {
|
||||
/*!
|
||||
/*
|
||||
\internal
|
||||
Converts the \a str string starting from the position pointed to by the \a
|
||||
it iterator, using the Unicode case traits \c Traits, and returns the
|
||||
|
@ -221,7 +221,7 @@ public:
|
||||
inline ~QString();
|
||||
QString &operator=(QChar c);
|
||||
QString &operator=(const QString &) Q_DECL_NOTHROW;
|
||||
inline QString &operator=(QLatin1String latin1);
|
||||
QString &operator=(QLatin1String latin1);
|
||||
#ifdef Q_COMPILER_RVALUE_REFS
|
||||
inline QString(QString && other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); }
|
||||
inline QString &operator=(QString &&other) Q_DECL_NOTHROW
|
||||
@ -885,11 +885,6 @@ inline void QString::detach()
|
||||
{ if (d->ref.isShared() || (d->offset != sizeof(QStringData))) reallocData(uint(d->size) + 1u); }
|
||||
inline bool QString::isDetached() const
|
||||
{ return !d->ref.isShared(); }
|
||||
inline QString &QString::operator=(QLatin1String s)
|
||||
{
|
||||
*this = fromLatin1(s.latin1(), s.size());
|
||||
return *this;
|
||||
}
|
||||
inline void QString::clear()
|
||||
{ if (!isNull()) *this = QString(); }
|
||||
inline QString::QString(const QString &other) Q_DECL_NOTHROW : d(other.d)
|
||||
|
@ -695,6 +695,11 @@ QTimeZone::OffsetData QTimeZone::offsetData(const QDateTime &forDateTime) const
|
||||
|
||||
/*!
|
||||
Returns \c true if the system backend supports obtaining transitions.
|
||||
|
||||
Transitions are changes in the time-zone: these happen when DST turns on or
|
||||
off and when authorities alter the offsets for the time-zone.
|
||||
|
||||
\sa nextTransition(), previousTransition(), transitions()
|
||||
*/
|
||||
|
||||
bool QTimeZone::hasTransitions() const
|
||||
|
@ -2967,15 +2967,6 @@ static void qInitImageConversions()
|
||||
#endif
|
||||
}
|
||||
|
||||
class QImageConversionsInitializer {
|
||||
public:
|
||||
QImageConversionsInitializer()
|
||||
{
|
||||
qInitImageConversions();
|
||||
}
|
||||
};
|
||||
|
||||
// Ensure initialization if this object file is linked.
|
||||
static QImageConversionsInitializer qImageConversionsInitializer;
|
||||
Q_CONSTRUCTOR_FUNCTION(qInitImageConversions);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -104,6 +104,7 @@ public:
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(StandardButtons, StandardButton)
|
||||
Q_FLAG(StandardButtons)
|
||||
|
||||
enum ButtonRole {
|
||||
// keep this in sync with QDialogButtonBox::ButtonRole and QMessageBox::ButtonRole
|
||||
@ -128,6 +129,7 @@ public:
|
||||
Reverse = 0x40000000,
|
||||
EOL = InvalidRole
|
||||
};
|
||||
Q_ENUM(ButtonRole)
|
||||
|
||||
enum ButtonLayout {
|
||||
// keep this in sync with QDialogButtonBox::ButtonLayout and QMessageBox::ButtonLayout
|
||||
@ -167,6 +169,7 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
class Q_GUI_EXPORT QColorDialogOptions
|
||||
{
|
||||
Q_GADGET
|
||||
public:
|
||||
enum ColorDialogOption {
|
||||
ShowAlphaChannel = 0x00000001,
|
||||
@ -175,6 +178,7 @@ public:
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(ColorDialogOptions, ColorDialogOption)
|
||||
Q_FLAG(ColorDialogOptions)
|
||||
|
||||
QColorDialogOptions();
|
||||
QColorDialogOptions(const QColorDialogOptions &rhs);
|
||||
@ -226,6 +230,7 @@ private:
|
||||
|
||||
class Q_GUI_EXPORT QFontDialogOptions
|
||||
{
|
||||
Q_GADGET
|
||||
public:
|
||||
enum FontDialogOption {
|
||||
NoButtons = 0x00000001,
|
||||
@ -237,6 +242,7 @@ public:
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(FontDialogOptions, FontDialogOption)
|
||||
Q_FLAG(FontDialogOptions)
|
||||
|
||||
QFontDialogOptions();
|
||||
QFontDialogOptions(const QFontDialogOptions &rhs);
|
||||
@ -279,11 +285,19 @@ private:
|
||||
|
||||
class Q_GUI_EXPORT QFileDialogOptions
|
||||
{
|
||||
Q_GADGET
|
||||
public:
|
||||
enum ViewMode { Detail, List };
|
||||
Q_ENUM(ViewMode)
|
||||
|
||||
enum FileMode { AnyFile, ExistingFile, Directory, ExistingFiles, DirectoryOnly };
|
||||
Q_ENUM(FileMode)
|
||||
|
||||
enum AcceptMode { AcceptOpen, AcceptSave };
|
||||
Q_ENUM(AcceptMode)
|
||||
|
||||
enum DialogLabel { LookIn, FileName, FileType, Accept, Reject, DialogLabelCount };
|
||||
Q_ENUM(DialogLabel)
|
||||
|
||||
enum FileDialogOption
|
||||
{
|
||||
@ -297,6 +311,7 @@ public:
|
||||
DontUseCustomDirectoryIcons = 0x00000080
|
||||
};
|
||||
Q_DECLARE_FLAGS(FileDialogOptions, FileDialogOption)
|
||||
Q_FLAG(FileDialogOptions)
|
||||
|
||||
QFileDialogOptions();
|
||||
QFileDialogOptions(const QFileDialogOptions &rhs);
|
||||
@ -396,9 +411,11 @@ private:
|
||||
|
||||
class Q_GUI_EXPORT QMessageDialogOptions
|
||||
{
|
||||
Q_GADGET
|
||||
public:
|
||||
// Keep in sync with QMessageBox::Icon
|
||||
enum Icon { NoIcon, Information, Warning, Critical, Question };
|
||||
Q_ENUM(Icon)
|
||||
|
||||
QMessageDialogOptions();
|
||||
QMessageDialogOptions(const QMessageDialogOptions &rhs);
|
||||
|
@ -63,6 +63,7 @@ public:
|
||||
// They could be added as public QAction roles if necessary.
|
||||
CutRole, CopyRole, PasteRole, SelectAllRole,
|
||||
RoleCount };
|
||||
Q_ENUM(MenuRole)
|
||||
|
||||
virtual void setTag(quintptr tag) = 0;
|
||||
virtual quintptr tag()const = 0;
|
||||
@ -91,6 +92,7 @@ class Q_GUI_EXPORT QPlatformMenu : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum MenuType { DefaultMenu = 0, EditMenu };
|
||||
Q_ENUM(MenuType)
|
||||
|
||||
virtual void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) = 0;
|
||||
virtual void removeMenuItem(QPlatformMenuItem *menuItem) = 0;
|
||||
|
@ -57,8 +57,10 @@ public:
|
||||
Trigger,
|
||||
MiddleClick
|
||||
};
|
||||
Q_ENUM(ActivationReason)
|
||||
|
||||
enum MessageIcon { NoIcon, Information, Warning, Critical };
|
||||
Q_ENUM(MessageIcon)
|
||||
|
||||
QPlatformSystemTrayIcon();
|
||||
~QPlatformSystemTrayIcon();
|
||||
|
@ -164,6 +164,8 @@ public:
|
||||
SmallFont,
|
||||
MiniFont,
|
||||
FixedFont,
|
||||
GroupBoxTitleFont,
|
||||
TabButtonFont,
|
||||
NFonts
|
||||
};
|
||||
|
||||
|
@ -116,8 +116,8 @@ QScreen::~QScreen()
|
||||
bool movingFromVirtualSibling = primaryScreen && primaryScreen->handle()->virtualSiblings().contains(handle());
|
||||
|
||||
// Move any leftover windows to the primary screen
|
||||
foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
|
||||
if (window->screen() != this)
|
||||
foreach (QWindow *window, QGuiApplication::allWindows()) {
|
||||
if (!window->isTopLevel() || window->screen() != this)
|
||||
continue;
|
||||
|
||||
const bool wasVisible = window->isVisible();
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include <qpa/qplatformwindow.h>
|
||||
|
||||
#include <QtCore/private/qobject_p.h>
|
||||
#include <QtCore/qelapsedtimer.h>
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -187,6 +188,7 @@ public:
|
||||
#endif
|
||||
|
||||
bool compositing;
|
||||
QElapsedTimer lastComposeTime;
|
||||
};
|
||||
|
||||
|
||||
|
@ -97,9 +97,11 @@ QOpenGLTexturePrivate::QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarge
|
||||
break;
|
||||
case QOpenGLTexture::TargetCubeMap:
|
||||
bindingTarget = QOpenGLTexture::BindingTargetCubeMap;
|
||||
faces = 6;
|
||||
break;
|
||||
case QOpenGLTexture::TargetCubeMapArray:
|
||||
bindingTarget = QOpenGLTexture::BindingTargetCubeMapArray;
|
||||
faces = 6;
|
||||
break;
|
||||
case QOpenGLTexture::Target2DMultisample:
|
||||
bindingTarget = QOpenGLTexture::BindingTarget2DMultisample;
|
||||
@ -175,7 +177,7 @@ bool QOpenGLTexturePrivate::create()
|
||||
|
||||
void QOpenGLTexturePrivate::destroy()
|
||||
{
|
||||
if (!context) {
|
||||
if (!textureId) {
|
||||
// not created or already destroyed
|
||||
return;
|
||||
}
|
||||
|
@ -156,7 +156,6 @@ public:
|
||||
bool autoGenerateMipMaps;
|
||||
bool storageAllocated;
|
||||
|
||||
QPair<int, int> glVersion;
|
||||
QOpenGLTextureHelper *texFuncs;
|
||||
|
||||
QOpenGLTexture::Features features;
|
||||
|
@ -32,11 +32,6 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include <qglobal.h>
|
||||
#ifdef Q_OS_IOS
|
||||
// We don't build the NEON drawhelpers as they are implemented partly
|
||||
// in GAS syntax assembly, which is not supported by the iOS toolchain.
|
||||
#undef __ARM_NEON__
|
||||
#endif
|
||||
|
||||
#include <qstylehints.h>
|
||||
#include <qguiapplication.h>
|
||||
@ -6314,8 +6309,13 @@ void qt_memfill32(quint32 *dest, quint32 color, int count)
|
||||
template<QtPixelOrder> const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *);
|
||||
#endif
|
||||
|
||||
extern void qInitBlendFunctions();
|
||||
|
||||
static void qInitDrawhelperFunctions()
|
||||
{
|
||||
// Set up basic blend function tables.
|
||||
qInitBlendFunctions();
|
||||
|
||||
#ifdef __SSE2__
|
||||
qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2;
|
||||
qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2;
|
||||
@ -6411,7 +6411,7 @@ static void qInitDrawhelperFunctions()
|
||||
|
||||
#endif // SSE2
|
||||
|
||||
#if defined(__ARM_NEON__) && !defined(Q_OS_IOS)
|
||||
#if defined(__ARM_NEON__)
|
||||
qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
|
||||
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
|
||||
qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
|
||||
@ -6432,7 +6432,7 @@ static void qInitDrawhelperFunctions()
|
||||
|
||||
qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon;
|
||||
|
||||
#if !defined(Q_PROCESSOR_ARM_64)
|
||||
#if defined(ENABLE_PIXMAN_DRAWHELPERS)
|
||||
// The RGB16 helpers are using Arm32 assemblythat has not been ported to AArch64
|
||||
qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16_neon;
|
||||
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB16] = qt_blend_rgb16_on_argb32_neon;
|
||||
@ -6509,19 +6509,7 @@ static void qInitDrawhelperFunctions()
|
||||
#endif // QT_COMPILER_SUPPORTS_MIPS_DSP || QT_COMPILER_SUPPORTS_MIPS_DSPR2
|
||||
}
|
||||
|
||||
extern void qInitBlendFunctions();
|
||||
class DrawHelperInitializer {
|
||||
public:
|
||||
DrawHelperInitializer()
|
||||
{
|
||||
// Set up basic blend function tables.
|
||||
qInitBlendFunctions();
|
||||
// Set up architecture optimized methods for the current machine.
|
||||
qInitDrawhelperFunctions();
|
||||
}
|
||||
};
|
||||
|
||||
// Ensure initialization if this object file is linked.
|
||||
static DrawHelperInitializer drawHelperInitializer;
|
||||
Q_CONSTRUCTOR_FUNCTION(qInitDrawhelperFunctions);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -3653,8 +3653,9 @@ QImage::Format QRasterBuffer::prepare(QImage *image)
|
||||
drawHelper = qDrawHelper + format;
|
||||
if (image->depth() == 1 && image->colorTable().size() == 2) {
|
||||
monoDestinationWithClut = true;
|
||||
destColor0 = qPremultiply(image->colorTable()[0]);
|
||||
destColor1 = qPremultiply(image->colorTable()[1]);
|
||||
const QVector<QRgb> colorTable = image->colorTable();
|
||||
destColor0 = qPremultiply(colorTable[0]);
|
||||
destColor1 = qPremultiply(colorTable[1]);
|
||||
}
|
||||
|
||||
return format;
|
||||
|
@ -301,6 +301,8 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i
|
||||
return;
|
||||
}
|
||||
|
||||
QWindowPrivate::get(window)->lastComposeTime.start();
|
||||
|
||||
QOpenGLFunctions *funcs = context->functions();
|
||||
funcs->glViewport(0, 0, window->width() * window->devicePixelRatio(), window->height() * window->devicePixelRatio());
|
||||
funcs->glClearColor(0, 0, 0, translucentBackground ? 0 : 1);
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "qimage.h"
|
||||
#include "qbitmap.h"
|
||||
|
||||
#include <qdebug.h>
|
||||
#include <private/qdebug_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -422,11 +422,32 @@ QDataStream &operator>>(QDataStream &s, QRegion &r)
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
QDebug operator<<(QDebug s, const QRegion &r)
|
||||
{
|
||||
QVector<QRect> rects = r.rects();
|
||||
s.nospace() << "QRegion(size=" << rects.size() << "), "
|
||||
<< "bounds = " << r.boundingRect() << '\n';
|
||||
for (int i=0; i<rects.size(); ++i)
|
||||
s << "- " << i << rects.at(i) << '\n';
|
||||
QDebugStateSaver saver(s);
|
||||
s.nospace();
|
||||
s << "QRegion(";
|
||||
if (r.isNull()) {
|
||||
s << "null";
|
||||
} else if (r.isEmpty()) {
|
||||
s << "empty";
|
||||
} else {
|
||||
const QVector<QRect> rects = r.rects();
|
||||
const int count = rects.size();
|
||||
if (count > 1)
|
||||
s << "size=" << count << ", bounds=(";
|
||||
QtDebugUtils::formatQRect(s, r.boundingRect());
|
||||
if (count > 1) {
|
||||
s << ") - [";
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (i)
|
||||
s << ", ";
|
||||
s << '(';
|
||||
QtDebugUtils::formatQRect(s, rects.at(i));
|
||||
s << ')';
|
||||
}
|
||||
s << ']';
|
||||
}
|
||||
}
|
||||
s << ')';
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
@ -2110,6 +2110,9 @@ QString QFont::lastResortFamily() const
|
||||
return QString::fromLatin1("helvetica");
|
||||
}
|
||||
|
||||
extern QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style,
|
||||
QFont::StyleHint styleHint, QChar::Script script);
|
||||
|
||||
/*!
|
||||
\fn QString QFont::defaultFamily() const
|
||||
|
||||
@ -2120,8 +2123,7 @@ QString QFont::lastResortFamily() const
|
||||
*/
|
||||
QString QFont::defaultFamily() const
|
||||
{
|
||||
QPlatformFontDatabase *fontDB = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
|
||||
const QStringList fallbacks = fontDB->fallbacksForFamily(QString(), QFont::StyleNormal
|
||||
const QStringList fallbacks = qt_fallbacksForFamily(QString(), QFont::StyleNormal
|
||||
, QFont::StyleHint(d->request.styleHint), QChar::Script_Common);
|
||||
if (!fallbacks.isEmpty())
|
||||
return fallbacks.first();
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include <qpa/qplatformfontdatabase.h>
|
||||
#include <qpa/qplatformtheme.h>
|
||||
|
||||
#include <QtCore/qcache.h>
|
||||
#include <QtCore/qmath.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -413,11 +414,45 @@ void QtFontFamily::ensurePopulated()
|
||||
Q_ASSERT_X(populated, Q_FUNC_INFO, qPrintable(name));
|
||||
}
|
||||
|
||||
|
||||
struct FallbacksCacheKey {
|
||||
QString family;
|
||||
QFont::Style style;
|
||||
QFont::StyleHint styleHint;
|
||||
QChar::Script script;
|
||||
};
|
||||
|
||||
inline bool operator==(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) Q_DECL_NOTHROW
|
||||
{
|
||||
return lhs.script == rhs.script &&
|
||||
lhs.styleHint == rhs.styleHint &&
|
||||
lhs.style == rhs.style &&
|
||||
lhs.family == rhs.family;
|
||||
}
|
||||
|
||||
inline bool operator!=(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) Q_DECL_NOTHROW
|
||||
{
|
||||
return !operator==(lhs, rhs);
|
||||
}
|
||||
|
||||
inline uint qHash(const FallbacksCacheKey &key, uint seed = 0) Q_DECL_NOTHROW
|
||||
{
|
||||
QtPrivate::QHashCombine hash;
|
||||
seed = hash(seed, key.family);
|
||||
seed = hash(seed, int(key.style));
|
||||
seed = hash(seed, int(key.styleHint));
|
||||
seed = hash(seed, int(key.script));
|
||||
return seed;
|
||||
}
|
||||
|
||||
|
||||
class QFontDatabasePrivate
|
||||
{
|
||||
public:
|
||||
QFontDatabasePrivate()
|
||||
: count(0), families(0), reregisterAppFonts(false)
|
||||
: count(0), families(0),
|
||||
fallbacksCache(64),
|
||||
reregisterAppFonts(false)
|
||||
{ }
|
||||
|
||||
~QFontDatabasePrivate() {
|
||||
@ -443,6 +478,7 @@ public:
|
||||
int count;
|
||||
QtFontFamily **families;
|
||||
|
||||
QCache<FallbacksCacheKey, QStringList> fallbacksCache;
|
||||
|
||||
|
||||
struct ApplicationFont {
|
||||
@ -461,6 +497,8 @@ public:
|
||||
void QFontDatabasePrivate::invalidate()
|
||||
{
|
||||
QFontCache::instance()->clear();
|
||||
|
||||
fallbacksCache.clear();
|
||||
free();
|
||||
QGuiApplicationPrivate::platformIntegration()->fontDatabase()->invalidate();
|
||||
emit static_cast<QGuiApplication *>(QCoreApplication::instance())->fontDatabaseChanged();
|
||||
@ -680,8 +718,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fontDatabaseMutex, (QMutex::Recursive))
|
||||
void qt_cleanupFontDatabase()
|
||||
{
|
||||
QFontDatabasePrivate *db = privateDb();
|
||||
if (db)
|
||||
if (db) {
|
||||
db->fallbacksCache.clear();
|
||||
db->free();
|
||||
}
|
||||
}
|
||||
|
||||
// used in qfontengine_x11.cpp
|
||||
@ -800,9 +840,15 @@ QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFo
|
||||
|
||||
QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
|
||||
{
|
||||
QFontDatabasePrivate *db = privateDb();
|
||||
|
||||
const FallbacksCacheKey cacheKey = { family, style, styleHint, script };
|
||||
|
||||
if (const QStringList *fallbacks = db->fallbacksCache.object(cacheKey))
|
||||
return *fallbacks;
|
||||
|
||||
// make sure that the db has all fallback families
|
||||
QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
|
||||
QFontDatabasePrivate *db = privateDb();
|
||||
|
||||
QStringList::iterator i;
|
||||
for (i = retList.begin(); i != retList.end(); ++i) {
|
||||
@ -818,6 +864,9 @@ QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFo
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
db->fallbacksCache.insert(cacheKey, new QStringList(retList));
|
||||
|
||||
return retList;
|
||||
}
|
||||
|
||||
|
@ -148,6 +148,9 @@ static void qt_qdnsservicerecord_sort(QList<QDnsServiceRecord> &records)
|
||||
}
|
||||
}
|
||||
|
||||
const char *QDnsLookupPrivate::msgNoIpV6NameServerAdresses =
|
||||
QT_TRANSLATE_NOOP("QDnsLookupRunnable", "IPv6 addresses for nameservers are currently not supported");
|
||||
|
||||
/*!
|
||||
\class QDnsLookup
|
||||
\brief The QDnsLookup class represents a DNS lookup.
|
||||
|
@ -89,6 +89,8 @@ public:
|
||||
|
||||
void _q_lookupFinished(const QDnsLookupReply &reply);
|
||||
|
||||
static const char *msgNoIpV6NameServerAdresses;
|
||||
|
||||
bool isFinished;
|
||||
QString name;
|
||||
QDnsLookup::Type type;
|
||||
|
@ -168,9 +168,9 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
|
||||
ns->sin6_addr.s6_addr[i] = ipv6Address[i];
|
||||
}
|
||||
#else
|
||||
qWarning("IPv6 addresses for nameservers is currently not supported");
|
||||
qWarning("%s", QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
|
||||
reply->error = QDnsLookup::ResolverError;
|
||||
reply->errorString = tr("IPv6 addresses for nameservers is currently not supported");
|
||||
reply->errorString = tr(QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
@ -60,9 +60,9 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
|
||||
// For supoprting IPv6 nameserver addresses, we'll need to switch
|
||||
// from DnsQuey() to DnsQueryEx() as it supports passing an IPv6
|
||||
// address in the nameserver list
|
||||
qWarning("IPv6 addresses for nameservers are currently not supported");
|
||||
qWarning("%s", QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
|
||||
reply->error = QDnsLookup::ResolverError;
|
||||
reply->errorString = tr("IPv6 addresses for nameservers are currently not supported");
|
||||
reply->errorString = tr(QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -360,10 +360,15 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
|
||||
{
|
||||
QList<QNetworkInterfacePrivate *> interfaces;
|
||||
QSet<QString> seenInterfaces;
|
||||
QVarLengthArray<int, 16> seenIndexes; // faster than QSet<int>
|
||||
|
||||
// on Linux, AF_PACKET addresses carry the hardware address and interface index;
|
||||
// scan for them first (they're usually first, but we have no guarantee this
|
||||
// will be the case forever)
|
||||
// On Linux, glibc, uClibc and MUSL obtain the address listing via two
|
||||
// netlink calls: first an RTM_GETLINK to obtain the interface listing,
|
||||
// then one RTM_GETADDR to get all the addresses (uClibc implementation is
|
||||
// copied from glibc; Bionic currently doesn't support getifaddrs). They
|
||||
// synthesize AF_PACKET addresses from the RTM_GETLINK responses, which
|
||||
// means by construction they currently show up first in the interface
|
||||
// listing.
|
||||
for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
|
||||
if (ptr->ifa_addr && ptr->ifa_addr->sa_family == AF_PACKET) {
|
||||
sockaddr_ll *sll = (sockaddr_ll *)ptr->ifa_addr;
|
||||
@ -374,23 +379,30 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
|
||||
iface->flags = convertFlags(ptr->ifa_flags);
|
||||
iface->hardwareAddress = iface->makeHwAddress(sll->sll_halen, (uchar*)sll->sll_addr);
|
||||
|
||||
Q_ASSERT(!seenIndexes.contains(iface->index));
|
||||
seenIndexes.append(iface->index);
|
||||
seenInterfaces.insert(iface->name);
|
||||
}
|
||||
}
|
||||
|
||||
// see if we missed anything:
|
||||
// virtual interfaces with no HW address have no AF_PACKET
|
||||
// - virtual interfaces with no HW address have no AF_PACKET
|
||||
// - interface labels have no AF_PACKET, but shouldn't be shown as a new interface
|
||||
for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
|
||||
if (ptr->ifa_addr && ptr->ifa_addr->sa_family != AF_PACKET) {
|
||||
QString name = QString::fromLatin1(ptr->ifa_name);
|
||||
if (seenInterfaces.contains(name))
|
||||
continue;
|
||||
|
||||
int ifindex = if_nametoindex(ptr->ifa_name);
|
||||
if (seenIndexes.contains(ifindex))
|
||||
continue;
|
||||
|
||||
QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
|
||||
interfaces << iface;
|
||||
iface->name = name;
|
||||
iface->flags = convertFlags(ptr->ifa_flags);
|
||||
iface->index = if_nametoindex(ptr->ifa_name);
|
||||
iface->index = ifindex;
|
||||
}
|
||||
}
|
||||
|
||||
@ -469,7 +481,7 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
|
||||
|
||||
interfaces = createInterfaces(interfaceListing);
|
||||
for (ifaddrs *ptr = interfaceListing; ptr; ptr = ptr->ifa_next) {
|
||||
// Get the interface index
|
||||
// Find the interface
|
||||
QString name = QString::fromLatin1(ptr->ifa_name);
|
||||
QNetworkInterfacePrivate *iface = 0;
|
||||
QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
|
||||
@ -479,6 +491,18 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
|
||||
iface = *if_it;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!iface) {
|
||||
// it may be an interface label, search by interface index
|
||||
int ifindex = if_nametoindex(ptr->ifa_name);
|
||||
for (if_it = interfaces.begin(); if_it != interfaces.end(); ++if_it)
|
||||
if ((*if_it)->index == ifindex) {
|
||||
// found this interface already
|
||||
iface = *if_it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!iface) {
|
||||
// skip all non-IP interfaces
|
||||
continue;
|
||||
|
@ -96,7 +96,7 @@ public:
|
||||
qint64 read(char *data, qint64 maxlen);
|
||||
qint64 write(const char *data, qint64 len);
|
||||
|
||||
qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *, PacketHeaderOptions);
|
||||
qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0, PacketHeaderOptions = WantNone);
|
||||
qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header);
|
||||
bool hasPendingDatagrams() const;
|
||||
qint64 pendingDatagramSize() const;
|
||||
|
@ -60,6 +60,15 @@ public:
|
||||
if (func)
|
||||
func(window, type);
|
||||
}
|
||||
|
||||
typedef void (*SetHasBorderInFullScreen)(QWindow *window, bool border);
|
||||
static const QByteArray setHasBorderInFullScreenIdentifier() { return QByteArrayLiteral("WindowsSetHasBorderInFullScreen"); }
|
||||
static void setHasBorderInFullScreen(QWindow *window, bool border)
|
||||
{
|
||||
SetHasBorderInFullScreen func = reinterpret_cast<SetHasBorderInFullScreen>(QGuiApplication::platformFunction(setHasBorderInFullScreenIdentifier()));
|
||||
if (func)
|
||||
func(window, border);
|
||||
}
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QWindowsWindowFunctions::TouchWindowTouchTypes)
|
||||
|
@ -69,3 +69,29 @@
|
||||
This is a convenience function that can be used directly instead of resolving the function pointer.
|
||||
\a window and \a type will be relayed to the function retrieved by QGuiApplication
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QWindowsWindowFunctions::SetHasBorderInFullScreen
|
||||
|
||||
This is the typedef for the function returned by QGuiApplication::platformFunction when passed setHasBorderInFullScreenIdentifier.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QByteArray QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier()
|
||||
\since 5.6
|
||||
|
||||
This function returns the bytearray that can be used to query
|
||||
QGuiApplication::platformFunction to retrieve the SetHasBorderInFullScreen function.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QWindowsWindowFunctions::setHasBorderInFullScreen(QWindow *window, bool border)
|
||||
\since 5.6
|
||||
|
||||
This is a convenience function that can be used directly instead of resolving the function pointer.
|
||||
\a window and \a border will be relayed to the function retrieved by QGuiApplication. When \a border
|
||||
is true then it will enable the WS_BORDER flag in full screen mode to enable other top level windows
|
||||
inside the application to appear on top when required.
|
||||
|
||||
See also \l [QtDoc] {Fullscreen OpenGL Based Windows}
|
||||
*/
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QPainter>
|
||||
#include <qpa/qplatformbackingstore.h>
|
||||
#include <private/qwindow_p.h>
|
||||
|
||||
#include "qopenglcompositorbackingstore_p.h"
|
||||
#include "qopenglcompositor_p.h"
|
||||
@ -198,6 +199,8 @@ void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegi
|
||||
|
||||
dstCtx->makeCurrent(dstWin);
|
||||
|
||||
QWindowPrivate::get(window)->lastComposeTime.start();
|
||||
|
||||
m_textures->clear();
|
||||
for (int i = 0; i < textures->count(); ++i)
|
||||
m_textures->appendTexture(textures->source(i), textures->textureId(i), textures->geometry(i),
|
||||
|
@ -263,11 +263,11 @@ QString TableGenerator::findComposeFile()
|
||||
{
|
||||
// check if XCOMPOSEFILE points to a Compose file
|
||||
if (qEnvironmentVariableIsSet("XCOMPOSEFILE")) {
|
||||
QString path(qgetenv("XCOMPOSEFILE"));
|
||||
if (path.endsWith(QLatin1String("Compose")))
|
||||
const QString path = QFile::decodeName(qgetenv("XCOMPOSEFILE"));
|
||||
if (QFile::exists(path))
|
||||
return path;
|
||||
else
|
||||
qWarning("Qt Warning: XCOMPOSEFILE doesn't point to a valid Compose file");
|
||||
qWarning("$XCOMPOSEFILE doesn't point to an existing file");
|
||||
}
|
||||
|
||||
// check if user’s home directory has a file named .XCompose
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <qplugin.h>
|
||||
#include <qdebug.h>
|
||||
|
||||
@ -91,6 +92,8 @@ extern "C" typedef int (*Main)(int, char **); //use the standard main method to
|
||||
static Main m_main = nullptr;
|
||||
static void *m_mainLibraryHnd = nullptr;
|
||||
static QList<QByteArray> m_applicationParams;
|
||||
pthread_t m_qtAppThread = 0;
|
||||
static sem_t m_exitSemaphore, m_terminateSemaphore;
|
||||
|
||||
struct SurfaceData
|
||||
{
|
||||
@ -454,6 +457,10 @@ static void *startMainMethod(void */*data*/)
|
||||
if (vm != 0)
|
||||
vm->DetachCurrentThread();
|
||||
|
||||
sem_post(&m_terminateSemaphore);
|
||||
sem_wait(&m_exitSemaphore);
|
||||
sem_destroy(&m_exitSemaphore);
|
||||
|
||||
// We must call exit() to ensure that all global objects will be destructed
|
||||
exit(ret);
|
||||
return 0;
|
||||
@ -503,8 +510,13 @@ static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring para
|
||||
return false;
|
||||
}
|
||||
|
||||
pthread_t appThread;
|
||||
return pthread_create(&appThread, nullptr, startMainMethod, nullptr) == 0;
|
||||
if (sem_init(&m_exitSemaphore, 0, 0) == -1)
|
||||
return false;
|
||||
|
||||
if (sem_init(&m_terminateSemaphore, 0, 0) == -1)
|
||||
return false;
|
||||
|
||||
return pthread_create(&m_qtAppThread, nullptr, startMainMethod, nullptr) == 0;
|
||||
}
|
||||
|
||||
|
||||
@ -518,6 +530,8 @@ static void quitQtAndroidPlugin(JNIEnv *env, jclass /*clazz*/)
|
||||
|
||||
static void terminateQt(JNIEnv *env, jclass /*clazz*/)
|
||||
{
|
||||
sem_wait(&m_terminateSemaphore);
|
||||
sem_destroy(&m_terminateSemaphore);
|
||||
env->DeleteGlobalRef(m_applicationClass);
|
||||
env->DeleteGlobalRef(m_classLoaderObject);
|
||||
if (m_resourcesObj)
|
||||
@ -535,6 +549,8 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/)
|
||||
m_androidPlatformIntegration = nullptr;
|
||||
delete m_androidAssetsFileEngineHandler;
|
||||
m_androidAssetsFileEngineHandler = nullptr;
|
||||
sem_post(&m_exitSemaphore);
|
||||
pthread_join(m_qtAppThread, nullptr);
|
||||
}
|
||||
|
||||
static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface, jint w, jint h)
|
||||
|
@ -74,7 +74,7 @@ QStringList QAndroidPlatformFontDatabase::fallbacksForFamily(const QString &fami
|
||||
result.append(QString(qgetenv("QT_ANDROID_FONTS_SERIF")).split(QLatin1Char(';')));
|
||||
else
|
||||
result.append(QString(qgetenv("QT_ANDROID_FONTS")).split(QLatin1Char(';')));
|
||||
result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script));
|
||||
result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -502,7 +502,11 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
|
||||
QMacAutoReleasePool pool;
|
||||
|
||||
if (m_contentViewIsEmbedded) {
|
||||
QPlatformWindow::setGeometry(rect);
|
||||
if (m_qtView) {
|
||||
[m_qtView setFrame:NSMakeRect(0, 0, rect.width(), rect.height())];
|
||||
} else {
|
||||
QPlatformWindow::setGeometry(rect);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -45,12 +45,15 @@
|
||||
QIOSContext::QIOSContext(QOpenGLContext *context)
|
||||
: QPlatformOpenGLContext()
|
||||
, m_sharedContext(static_cast<QIOSContext *>(context->shareHandle()))
|
||||
, m_eaglContext(0)
|
||||
, m_format(context->format())
|
||||
{
|
||||
m_format.setRenderableType(QSurfaceFormat::OpenGLES);
|
||||
m_eaglContext = [[EAGLContext alloc]
|
||||
initWithAPI:EAGLRenderingAPI(m_format.majorVersion())
|
||||
sharegroup:m_sharedContext ? [m_sharedContext->m_eaglContext sharegroup] : nil];
|
||||
|
||||
EAGLSharegroup *shareGroup = m_sharedContext ? [m_sharedContext->m_eaglContext sharegroup] : nil;
|
||||
const int preferredVersion = m_format.majorVersion() == 1 ? kEAGLRenderingAPIOpenGLES1 : kEAGLRenderingAPIOpenGLES3;
|
||||
for (int version = preferredVersion; !m_eaglContext && version >= m_format.majorVersion(); --version)
|
||||
m_eaglContext = [[EAGLContext alloc] initWithAPI:EAGLRenderingAPI(version) sharegroup:shareGroup];
|
||||
|
||||
if (m_eaglContext != nil) {
|
||||
EAGLContext *originalContext = [EAGLContext currentContext];
|
||||
|
@ -62,11 +62,23 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
|
||||
{
|
||||
if (self = [super init]) {
|
||||
[self setVisibleMenuItems:visibleMenuItems];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(menuClosed)
|
||||
name:UIMenuControllerDidHideMenuNotification object:nil];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver:self
|
||||
name:UIMenuControllerDidHideMenuNotification object:nil];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)setVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems
|
||||
{
|
||||
m_visibleMenuItems = visibleMenuItems;
|
||||
@ -86,6 +98,11 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
|
||||
[[UIMenuController sharedMenuController] setMenuVisible:YES animated:NO];
|
||||
}
|
||||
|
||||
-(void)menuClosed
|
||||
{
|
||||
QIOSMenu::currentMenu()->dismiss();
|
||||
}
|
||||
|
||||
- (id)targetForAction:(SEL)action withSender:(id)sender
|
||||
{
|
||||
Q_UNUSED(sender);
|
||||
|
@ -318,7 +318,11 @@
|
||||
// a regular responder transfer to another window. In the former case, iOS
|
||||
// will set the new first-responder to our next-responder, and in the latter
|
||||
// case we'll have an active responder candidate.
|
||||
if ([UIResponder currentFirstResponder] == [self nextResponder]) {
|
||||
if (![UIResponder currentFirstResponder]) {
|
||||
// No first responder set anymore, sync this with Qt by clearing the
|
||||
// focus object.
|
||||
m_inputContext->clearCurrentFocusObject();
|
||||
} else if ([UIResponder currentFirstResponder] == [self nextResponder]) {
|
||||
// We have resigned the keyboard, and transferred first responder back to the parent view
|
||||
Q_ASSERT(!FirstResponderCandidate::currentCandidate());
|
||||
if ([self currentImeState:Qt::ImEnabled].toBool()) {
|
||||
@ -364,6 +368,32 @@
|
||||
[self sendKeyPressRelease:key modifiers:modifiers];
|
||||
}
|
||||
|
||||
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
|
||||
{
|
||||
bool isEditAction = (action == @selector(cut:)
|
||||
|| action == @selector(copy:)
|
||||
|| action == @selector(paste:)
|
||||
|| action == @selector(delete:)
|
||||
|| action == @selector(toggleBoldface:)
|
||||
|| action == @selector(toggleItalics:)
|
||||
|| action == @selector(toggleUnderline:)
|
||||
|| action == @selector(undo)
|
||||
|| action == @selector(redo));
|
||||
|
||||
bool isSelectAction = (action == @selector(select:)
|
||||
|| action == @selector(selectAll:)
|
||||
|| action == @selector(paste:)
|
||||
|| action == @selector(undo)
|
||||
|| action == @selector(redo));
|
||||
|
||||
const bool unknownAction = !isEditAction && !isSelectAction;
|
||||
const bool hasSelection = ![self selectedTextRange].empty;
|
||||
|
||||
if (unknownAction)
|
||||
return [super canPerformAction:action withSender:sender];
|
||||
return (hasSelection && isEditAction) || (!hasSelection && isSelectAction);
|
||||
}
|
||||
|
||||
- (void)cut:(id)sender
|
||||
{
|
||||
Q_UNUSED(sender);
|
||||
@ -382,6 +412,13 @@
|
||||
[self sendShortcut:QKeySequence::Paste];
|
||||
}
|
||||
|
||||
- (void)select:(id)sender
|
||||
{
|
||||
Q_UNUSED(sender);
|
||||
[self sendShortcut:QKeySequence::MoveToPreviousWord];
|
||||
[self sendShortcut:QKeySequence::SelectNextWord];
|
||||
}
|
||||
|
||||
- (void)selectAll:(id)sender
|
||||
{
|
||||
Q_UNUSED(sender);
|
||||
@ -580,7 +617,8 @@
|
||||
|
||||
- (UITextPosition *)endOfDocument
|
||||
{
|
||||
int endPosition = [self currentImeState:Qt::ImSurroundingText].toString().length();
|
||||
QString surroundingText = [self currentImeState:Qt::ImSurroundingText].toString();
|
||||
int endPosition = surroundingText.length() + m_markedText.length();
|
||||
return [QUITextPosition positionWithIndex:endPosition];
|
||||
}
|
||||
|
||||
@ -611,9 +649,18 @@
|
||||
|
||||
- (NSString *)textInRange:(UITextRange *)range
|
||||
{
|
||||
QString text = [self currentImeState:Qt::ImSurroundingText].toString();
|
||||
if (!m_markedText.isEmpty()) {
|
||||
// [UITextInput textInRange] is sparsely documented, but it turns out that unconfirmed
|
||||
// marked text should be seen as a part of the text document. This is different from
|
||||
// ImSurroundingText, which excludes it.
|
||||
int cursorPos = [self currentImeState:Qt::ImCursorPosition].toInt();
|
||||
text = text.left(cursorPos) + m_markedText + text.mid(cursorPos);
|
||||
}
|
||||
|
||||
int s = static_cast<QUITextPosition *>([range start]).index;
|
||||
int e = static_cast<QUITextPosition *>([range end]).index;
|
||||
return [self currentImeState:Qt::ImSurroundingText].toString().mid(s, e - s).toNSString();
|
||||
return text.mid(s, e - s).toNSString();
|
||||
}
|
||||
|
||||
- (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange
|
||||
@ -882,6 +929,14 @@
|
||||
if ([text isEqualToString:@"\n"]) {
|
||||
[self sendKeyPressRelease:Qt::Key_Return modifiers:Qt::NoModifier];
|
||||
|
||||
// An onEnter handler of a TextInput might move to the next input by calling
|
||||
// nextInput.forceActiveFocus() which changes the focusObject.
|
||||
// In that case we don't want to hide the VKB.
|
||||
if (focusObject != QGuiApplication::focusObject()) {
|
||||
qImDebug() << "focusObject already changed, not resigning first responder.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.returnKeyType == UIReturnKeyDone || self.returnKeyType == UIReturnKeyGo
|
||||
|| self.returnKeyType == UIReturnKeySend || self.returnKeyType == UIReturnKeySearch)
|
||||
[self resignFirstResponder];
|
||||
|
@ -96,7 +96,12 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion ®ion,
|
||||
RECT dirty = {dirtyRect.x(), dirtyRect.y(),
|
||||
dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()};
|
||||
UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, &ptDst, &size, m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA, &dirty};
|
||||
QWindowsContext::user32dll.updateLayeredWindowIndirect(rw->handle(), &info);
|
||||
const BOOL result = QWindowsContext::user32dll.updateLayeredWindowIndirect(rw->handle(), &info);
|
||||
if (!result)
|
||||
qErrnoWarning("UpdateLayeredWindowIndirect failed for ptDst=(%d, %d),"
|
||||
" size=(%dx%d), dirty=(%dx%d %d, %d)", r.x(), r.y(),
|
||||
r.width(), r.height(), dirtyRect.width(), dirtyRect.height(),
|
||||
dirtyRect.x(), dirtyRect.y());
|
||||
} else {
|
||||
QWindowsContext::user32dll.updateLayeredWindow(rw->handle(), NULL, &ptDst, &size, m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA);
|
||||
}
|
||||
|
@ -192,7 +192,14 @@ typedef struct {
|
||||
quint16 stringOffset;
|
||||
} NAME_RECORD;
|
||||
|
||||
static QString fontNameFromTTFile(const QString &filename)
|
||||
typedef struct {
|
||||
quint32 tag;
|
||||
quint16 majorVersion;
|
||||
quint16 minorVersion;
|
||||
quint32 numFonts;
|
||||
} TTC_TABLE_HEADER;
|
||||
|
||||
static QString fontNameFromTTFile(const QString &filename, int startPos = 0)
|
||||
{
|
||||
QFile f(filename);
|
||||
QString retVal;
|
||||
@ -200,6 +207,7 @@ static QString fontNameFromTTFile(const QString &filename)
|
||||
qint64 bytesToRead;
|
||||
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
f.seek(startPos);
|
||||
OFFSET_TABLE ttOffsetTable;
|
||||
bytesToRead = sizeof(OFFSET_TABLE);
|
||||
bytesRead = f.read((char*)&ttOffsetTable, bytesToRead);
|
||||
@ -280,6 +288,37 @@ static QString fontNameFromTTFile(const QString &filename)
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static QStringList fontNamesFromTTCFile(const QString &filename)
|
||||
{
|
||||
QFile f(filename);
|
||||
QStringList retVal;
|
||||
qint64 bytesRead;
|
||||
qint64 bytesToRead;
|
||||
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
TTC_TABLE_HEADER ttcTableHeader;
|
||||
bytesToRead = sizeof(TTC_TABLE_HEADER);
|
||||
bytesRead = f.read((char*)&ttcTableHeader, bytesToRead);
|
||||
if (bytesToRead != bytesRead)
|
||||
return retVal;
|
||||
ttcTableHeader.majorVersion = qFromBigEndian(ttcTableHeader.majorVersion);
|
||||
ttcTableHeader.minorVersion = qFromBigEndian(ttcTableHeader.minorVersion);
|
||||
ttcTableHeader.numFonts = qFromBigEndian(ttcTableHeader.numFonts);
|
||||
|
||||
if (ttcTableHeader.majorVersion < 1 || ttcTableHeader.majorVersion > 2)
|
||||
return retVal;
|
||||
QVarLengthArray<quint32> offsetTable(ttcTableHeader.numFonts);
|
||||
bytesToRead = sizeof(offsetTable) * ttcTableHeader.numFonts;
|
||||
bytesRead = f.read((char*)offsetTable.data(), bytesToRead);
|
||||
if (bytesToRead != bytesRead)
|
||||
return retVal;
|
||||
f.close();
|
||||
for (int i = 0; i < (int)ttcTableHeader.numFonts; ++i)
|
||||
retVal << fontNameFromTTFile(filename, qFromBigEndian(offsetTable[i]));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static inline QString fontSettingsOrganization() { return QStringLiteral("Qt-Project"); }
|
||||
static inline QString fontSettingsApplication() { return QStringLiteral("Qtbase"); }
|
||||
static inline QString fontSettingsGroup() { return QStringLiteral("CEFontCache"); }
|
||||
@ -306,20 +345,28 @@ static QString findFontFile(const QString &faceName)
|
||||
//empty the cache first, as it seems that it is dirty
|
||||
settings.remove(QString());
|
||||
|
||||
QDirIterator it(QStringLiteral("/Windows"), QStringList(QStringLiteral("*.ttf")), QDir::Files | QDir::Hidden | QDir::System);
|
||||
|
||||
QDirIterator it(QStringLiteral("/Windows"), QStringList() << QStringLiteral("*.ttf") << QStringLiteral("*.ttc"), QDir::Files | QDir::Hidden | QDir::System);
|
||||
const QLatin1Char lowerF('f');
|
||||
const QLatin1Char upperF('F');
|
||||
while (it.hasNext()) {
|
||||
const QString fontFile = it.next();
|
||||
const QString fontName = fontNameFromTTFile(fontFile);
|
||||
if (fontName.isEmpty())
|
||||
continue;
|
||||
fontCache.insert(fontName, fontFile);
|
||||
settings.setValue(fontName, fontFile);
|
||||
QStringList fontNames;
|
||||
const QChar c = fontFile[fontFile.size() - 1];
|
||||
if (c == lowerF || c == upperF)
|
||||
fontNames << fontNameFromTTFile(fontFile);
|
||||
else
|
||||
fontNames << fontNamesFromTTCFile(fontFile);
|
||||
foreach (const QString fontName, fontNames) {
|
||||
if (fontName.isEmpty())
|
||||
continue;
|
||||
fontCache.insert(fontName, fontFile);
|
||||
settings.setValue(fontName, fontFile);
|
||||
|
||||
if (localizedName(fontName)) {
|
||||
QString englishFontName = getEnglishName(fontName);
|
||||
fontCache.insert(englishFontName, fontFile);
|
||||
settings.setValue(englishFontName, fontFile);
|
||||
if (localizedName(fontName)) {
|
||||
QString englishFontName = getEnglishName(fontName);
|
||||
fontCache.insert(englishFontName, fontFile);
|
||||
settings.setValue(englishFontName, fontFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
settings.endGroup();
|
||||
@ -675,7 +722,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF
|
||||
|
||||
result.append(QWindowsFontDatabase::extraTryFontsForFamily(family));
|
||||
|
||||
result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script));
|
||||
result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script));
|
||||
|
||||
qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
|
||||
<< script << result;
|
||||
|
@ -485,9 +485,9 @@ qreal QWindowsFontEngineDirectWrite::maxCharWidth() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)
|
||||
QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)
|
||||
{
|
||||
QImage im = imageForGlyph(glyph, subPixelPosition, 0, QTransform());
|
||||
QImage im = alphaRGBMapForGlyph(glyph, subPixelPosition, t);
|
||||
|
||||
QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8);
|
||||
|
||||
@ -504,6 +504,11 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed sub
|
||||
return alphaMap;
|
||||
}
|
||||
|
||||
QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)
|
||||
{
|
||||
return alphaMapForGlyph(glyph, subPixelPosition, QTransform());
|
||||
}
|
||||
|
||||
bool QWindowsFontEngineDirectWrite::supportsSubPixelPositions() const
|
||||
{
|
||||
return true;
|
||||
@ -709,9 +714,9 @@ QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyN
|
||||
glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed pos, const QTransform &matrix, GlyphFormat format)
|
||||
{
|
||||
Q_UNUSED(pos);
|
||||
int margin = 0;
|
||||
if (format == QFontEngine::Format_A32 || format == QFontEngine::Format_ARGB)
|
||||
margin = glyphMargin(QFontEngine::Format_A32);
|
||||
Q_UNUSED(format);
|
||||
|
||||
int margin = glyphMargin(QFontEngine::Format_A32);
|
||||
glyph_metrics_t gm = QFontEngine::boundingBox(glyph, matrix);
|
||||
gm.width += margin * 2;
|
||||
gm.height += margin * 2;
|
||||
|
@ -86,6 +86,7 @@ public:
|
||||
bool supportsSubPixelPositions() const;
|
||||
|
||||
QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition);
|
||||
QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t);
|
||||
QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform);
|
||||
|
||||
QFontEngine *cloneWithSize(qreal pixelSize) const;
|
||||
|
@ -86,10 +86,15 @@ QT_BEGIN_NAMESPACE
|
||||
The code originates from \c qkeymapper_win.cpp.
|
||||
*/
|
||||
|
||||
static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state);
|
||||
|
||||
QWindowsKeyMapper::QWindowsKeyMapper()
|
||||
: m_useRTLExtensions(false), m_keyGrabber(0)
|
||||
{
|
||||
memset(keyLayout, 0, sizeof(keyLayout));
|
||||
QGuiApplication *app = static_cast<QGuiApplication *>(QGuiApplication::instance());
|
||||
QObject::connect(app, &QGuiApplication::applicationStateChanged,
|
||||
app, clearKeyRecorderOnApplicationInActive);
|
||||
}
|
||||
|
||||
QWindowsKeyMapper::~QWindowsKeyMapper()
|
||||
@ -144,6 +149,12 @@ struct KeyRecorder
|
||||
};
|
||||
static KeyRecorder key_recorder;
|
||||
|
||||
static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state)
|
||||
{
|
||||
if (state == Qt::ApplicationInactive)
|
||||
key_recorder.clearKeys();
|
||||
}
|
||||
|
||||
KeyRecord *KeyRecorder::findKey(int code, bool remove)
|
||||
{
|
||||
KeyRecord *result = 0;
|
||||
|
@ -245,6 +245,8 @@ QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &fun
|
||||
{
|
||||
if (function == QWindowsWindowFunctions::setTouchWindowTouchTypeIdentifier())
|
||||
return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic);
|
||||
else if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier())
|
||||
return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic);
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
|
||||
|
@ -1720,7 +1720,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
|
||||
if (!m_savedStyle) {
|
||||
m_savedStyle = style();
|
||||
#ifndef Q_OS_WINCE
|
||||
if (oldState == Qt::WindowMinimized) {
|
||||
if (oldState == Qt::WindowMinimized || oldState == Qt::WindowMaximized) {
|
||||
const QRect nf = normalFrameGeometry(m_data.hwnd);
|
||||
if (nf.isValid())
|
||||
m_savedFrameGeometry = nf;
|
||||
@ -1735,6 +1735,8 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
|
||||
newStyle |= WS_SYSMENU;
|
||||
if (visible)
|
||||
newStyle |= WS_VISIBLE;
|
||||
if (testFlag(HasBorderInFullScreen))
|
||||
newStyle |= WS_BORDER;
|
||||
setStyle(newStyle);
|
||||
// Use geometry of QWindow::screen() within creation or the virtual screen the
|
||||
// window is in (QTBUG-31166, QTBUG-30724).
|
||||
@ -1769,7 +1771,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
|
||||
// preserve maximized state
|
||||
if (visible) {
|
||||
setFlag(WithinMaximize);
|
||||
ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
|
||||
ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA);
|
||||
clearFlag(WithinMaximize);
|
||||
}
|
||||
m_savedStyle = 0;
|
||||
@ -2371,4 +2373,19 @@ void QWindowsWindow::aboutToMakeCurrent()
|
||||
#endif
|
||||
}
|
||||
|
||||
void QWindowsWindow::setHasBorderInFullScreenStatic(QWindow *window, bool border)
|
||||
{
|
||||
if (!window->handle())
|
||||
return;
|
||||
static_cast<QWindowsWindow *>(window->handle())->setHasBorderInFullScreen(border);
|
||||
}
|
||||
|
||||
void QWindowsWindow::setHasBorderInFullScreen(bool border)
|
||||
{
|
||||
if (border)
|
||||
setFlag(HasBorderInFullScreen);
|
||||
else
|
||||
clearFlag(HasBorderInFullScreen);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -137,7 +137,8 @@ public:
|
||||
WithinMaximize = 0x40000,
|
||||
MaximizeToFullScreen = 0x80000,
|
||||
InputMethodDisabled = 0x100000,
|
||||
Compositing = 0x200000
|
||||
Compositing = 0x200000,
|
||||
HasBorderInFullScreen = 0x400000
|
||||
};
|
||||
|
||||
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
|
||||
@ -251,7 +252,8 @@ public:
|
||||
|
||||
static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes);
|
||||
void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch);
|
||||
|
||||
static void setHasBorderInFullScreenStatic(QWindow *window, bool border);
|
||||
void setHasBorderInFullScreen(bool border);
|
||||
private:
|
||||
inline void show_sys() const;
|
||||
inline void hide_sys() const;
|
||||
|
@ -428,6 +428,21 @@ QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handl
|
||||
return engine;
|
||||
}
|
||||
|
||||
QStringList QWinRTFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style,
|
||||
QFont::StyleHint styleHint,
|
||||
QChar::Script script) const
|
||||
{
|
||||
Q_UNUSED(style)
|
||||
Q_UNUSED(styleHint)
|
||||
Q_UNUSED(script)
|
||||
|
||||
QStringList result;
|
||||
if (family == QLatin1String("Helvetica"))
|
||||
result.append(QStringLiteral("Arial"));
|
||||
result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script));
|
||||
return result;
|
||||
}
|
||||
|
||||
void QWinRTFontDatabase::releaseHandle(void *handle)
|
||||
{
|
||||
if (!handle)
|
||||
|
@ -60,6 +60,8 @@ public:
|
||||
void populateFontDatabase() Q_DECL_OVERRIDE;
|
||||
void populateFamily(const QString &familyName) Q_DECL_OVERRIDE;
|
||||
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE;
|
||||
QStringList fallbacksForFamily(const QString &family, QFont::Style style,
|
||||
QFont::StyleHint styleHint, QChar::Script script) const Q_DECL_OVERRIDE;
|
||||
void releaseHandle(void *handle) Q_DECL_OVERRIDE;
|
||||
private:
|
||||
QHash<IDWriteFontFile *, FontDescription> m_fonts;
|
||||
|
@ -179,42 +179,6 @@ QXcbScreen* QXcbConnection::findScreenForOutput(xcb_window_t rootWindow, xcb_ran
|
||||
return 0;
|
||||
}
|
||||
|
||||
QXcbScreen* QXcbConnection::createScreen(QXcbVirtualDesktop* virtualDesktop,
|
||||
xcb_randr_output_t outputId,
|
||||
xcb_randr_get_output_info_reply_t *output)
|
||||
{
|
||||
QString name;
|
||||
if (output)
|
||||
name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output),
|
||||
xcb_randr_get_output_info_name_length(output));
|
||||
else {
|
||||
QByteArray displayName = m_displayName;
|
||||
int dotPos = displayName.lastIndexOf('.');
|
||||
if (dotPos != -1)
|
||||
displayName.truncate(dotPos);
|
||||
name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + QString::number(virtualDesktop->number());
|
||||
}
|
||||
|
||||
return new QXcbScreen(this, virtualDesktop, outputId, output, name);
|
||||
}
|
||||
|
||||
bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output)
|
||||
{
|
||||
xcb_generic_error_t *error = 0;
|
||||
xcb_randr_get_output_primary_cookie_t primaryCookie =
|
||||
xcb_randr_get_output_primary(xcb_connection(), rootWindow);
|
||||
QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary (
|
||||
xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error));
|
||||
if (!primary || error) {
|
||||
qWarning("failed to get the primary output of the screen");
|
||||
free(error);
|
||||
error = NULL;
|
||||
}
|
||||
const bool isPrimary = primary ? (primary->output == output) : false;
|
||||
|
||||
return isPrimary;
|
||||
}
|
||||
|
||||
QXcbVirtualDesktop* QXcbConnection::virtualDesktopForRootWindow(xcb_window_t rootWindow)
|
||||
{
|
||||
foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops) {
|
||||
@ -237,8 +201,9 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
|
||||
// Not for us
|
||||
return;
|
||||
|
||||
qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc;
|
||||
QXcbScreen *screen = findScreenForCrtc(crtc.window, crtc.crtc);
|
||||
qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc
|
||||
<< "mode" << crtc.mode << "relevant screen" << screen;
|
||||
// Only update geometry when there's a valid mode on the CRTC
|
||||
// CRTC with node mode could mean that output has been disabled, and we'll
|
||||
// get RRNotifyOutputChange notification for that.
|
||||
@ -260,16 +225,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
|
||||
|
||||
if (screen && output.connection == XCB_RANDR_CONNECTION_DISCONNECTED) {
|
||||
qCDebug(lcQpaScreen) << "screen" << screen->name() << "has been disconnected";
|
||||
|
||||
// Known screen removed -> delete it
|
||||
m_screens.removeOne(screen);
|
||||
virtualDesktop->removeScreen(screen);
|
||||
|
||||
QXcbIntegration::instance()->destroyScreen(screen);
|
||||
|
||||
// QTBUG-40174, QTBUG-42985: If all screens are removed, wait
|
||||
// and start rendering again later if a screen becomes available.
|
||||
|
||||
destroyScreen(screen);
|
||||
} else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) {
|
||||
// New XRandR output is available and it's enabled
|
||||
if (output.crtc != XCB_NONE && output.mode != XCB_NONE) {
|
||||
@ -278,59 +234,142 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
|
||||
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
|
||||
xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
|
||||
|
||||
screen = createScreen(virtualDesktop, output.output, outputInfo.data());
|
||||
qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
|
||||
// Find a fake screen
|
||||
foreach (QPlatformScreen *scr, virtualDesktop->screens()) {
|
||||
QXcbScreen *xcbScreen = (QXcbScreen *)scr;
|
||||
if (xcbScreen->output() == XCB_NONE) {
|
||||
screen = xcbScreen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
screen->setPrimary(checkOutputIsPrimary(output.window, output.output));
|
||||
virtualDesktop->addScreen(screen);
|
||||
m_screens << screen;
|
||||
QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
|
||||
|
||||
// Windows which had null screens have already had expose events by now.
|
||||
// They need to be told the screen is back, it's OK to render.
|
||||
foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
|
||||
QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle());
|
||||
if (xcbWin)
|
||||
xcbWin->maybeSetScreen(screen);
|
||||
if (screen) {
|
||||
QString nameWas = screen->name();
|
||||
// Transform the fake screen into a physical screen
|
||||
screen->setOutput(output.output, outputInfo.data());
|
||||
updateScreen(screen, output);
|
||||
qCDebug(lcQpaScreen) << "output" << screen->name()
|
||||
<< "is connected and enabled; was fake:" << nameWas;
|
||||
} else {
|
||||
screen = createScreen(virtualDesktop, output, outputInfo.data());
|
||||
qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
|
||||
}
|
||||
}
|
||||
// else ignore disabled screens
|
||||
} else if (screen) {
|
||||
// Screen has been disabled -> remove
|
||||
if (output.crtc == XCB_NONE && output.mode == XCB_NONE) {
|
||||
// Screen has been disabled
|
||||
xcb_randr_get_output_info_cookie_t outputInfoCookie =
|
||||
xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp);
|
||||
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
|
||||
xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
|
||||
if (outputInfo->crtc == XCB_NONE) {
|
||||
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled";
|
||||
m_screens.removeOne(screen);
|
||||
virtualDesktop->removeScreen(screen);
|
||||
QXcbIntegration::instance()->destroyScreen(screen);
|
||||
destroyScreen(screen);
|
||||
} else {
|
||||
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been temporarily disabled for the mode switch";
|
||||
// Reset crtc to skip RRCrtcChangeNotify events,
|
||||
// because they may be invalid in the middle of the mode switch
|
||||
screen->setCrtc(XCB_NONE);
|
||||
}
|
||||
} else {
|
||||
// Just update existing screen
|
||||
screen->updateGeometry(output.config_timestamp);
|
||||
const bool wasPrimary = screen->isPrimary();
|
||||
screen->setPrimary(checkOutputIsPrimary(output.window, output.output));
|
||||
if (screen->mode() != output.mode)
|
||||
screen->updateRefreshRate(output.mode);
|
||||
|
||||
// If the screen became primary, reshuffle the order in QGuiApplicationPrivate
|
||||
if (!wasPrimary && screen->isPrimary()) {
|
||||
const int idx = m_screens.indexOf(screen);
|
||||
m_screens.swap(0, idx);
|
||||
QXcbIntegration::instance()->setPrimaryScreen(screen);
|
||||
}
|
||||
updateScreen(screen, output);
|
||||
qCDebug(lcQpaScreen) << "output has changed" << screen;
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
|
||||
}
|
||||
}
|
||||
|
||||
bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output)
|
||||
{
|
||||
xcb_generic_error_t *error = 0;
|
||||
xcb_randr_get_output_primary_cookie_t primaryCookie =
|
||||
xcb_randr_get_output_primary(xcb_connection(), rootWindow);
|
||||
QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary (
|
||||
xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error));
|
||||
if (!primary || error) {
|
||||
qWarning("failed to get the primary output of the screen");
|
||||
free(error);
|
||||
error = NULL;
|
||||
}
|
||||
const bool isPrimary = primary ? (primary->output == output) : false;
|
||||
|
||||
return isPrimary;
|
||||
}
|
||||
|
||||
void QXcbConnection::updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange)
|
||||
{
|
||||
screen->setCrtc(outputChange.crtc); // Set the new crtc, because it can be invalid
|
||||
screen->updateGeometry(outputChange.config_timestamp);
|
||||
if (screen->mode() != outputChange.mode)
|
||||
screen->updateRefreshRate(outputChange.mode);
|
||||
// Only screen which belongs to the primary virtual desktop can be a primary screen
|
||||
if (screen->screenNumber() == m_primaryScreenNumber) {
|
||||
if (!screen->isPrimary() && checkOutputIsPrimary(outputChange.window, outputChange.output)) {
|
||||
screen->setPrimary(true);
|
||||
|
||||
// If the screen became primary, reshuffle the order in QGuiApplicationPrivate
|
||||
const int idx = m_screens.indexOf(screen);
|
||||
if (idx > 0) {
|
||||
m_screens.first()->setPrimary(false);
|
||||
m_screens.swap(0, idx);
|
||||
}
|
||||
screen->virtualDesktop()->setPrimaryScreen(screen);
|
||||
QXcbIntegration::instance()->setPrimaryScreen(screen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QXcbScreen *QXcbConnection::createScreen(QXcbVirtualDesktop *virtualDesktop,
|
||||
const xcb_randr_output_change_t &outputChange,
|
||||
xcb_randr_get_output_info_reply_t *outputInfo)
|
||||
{
|
||||
QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputChange.output, outputInfo);
|
||||
// Only screen which belongs to the primary virtual desktop can be a primary screen
|
||||
if (screen->screenNumber() == m_primaryScreenNumber)
|
||||
screen->setPrimary(checkOutputIsPrimary(outputChange.window, outputChange.output));
|
||||
|
||||
if (screen->isPrimary()) {
|
||||
if (!m_screens.isEmpty())
|
||||
qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
|
||||
else
|
||||
qCDebug(lcQpaScreen) << "no outputs";
|
||||
m_screens.first()->setPrimary(false);
|
||||
|
||||
m_screens.prepend(screen);
|
||||
} else {
|
||||
m_screens.append(screen);
|
||||
}
|
||||
virtualDesktop->addScreen(screen);
|
||||
QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
void QXcbConnection::destroyScreen(QXcbScreen *screen)
|
||||
{
|
||||
QXcbVirtualDesktop *virtualDesktop = screen->virtualDesktop();
|
||||
if (virtualDesktop->screens().count() == 1) {
|
||||
// If there are no other screens on the same virtual desktop,
|
||||
// then transform the physical screen into a fake screen.
|
||||
const QString nameWas = screen->name();
|
||||
screen->setOutput(XCB_NONE, Q_NULLPTR);
|
||||
qCDebug(lcQpaScreen) << "transformed" << nameWas << "to fake" << screen;
|
||||
} else {
|
||||
// There is more than one screen on the same virtual desktop, remove the screen
|
||||
m_screens.removeOne(screen);
|
||||
virtualDesktop->removeScreen(screen);
|
||||
|
||||
// When primary screen is removed, set the new primary screen
|
||||
// which belongs to the primary virtual desktop.
|
||||
if (screen->isPrimary()) {
|
||||
QXcbScreen *newPrimary = (QXcbScreen *)virtualDesktop->screens().at(0);
|
||||
newPrimary->setPrimary(true);
|
||||
const int idx = m_screens.indexOf(newPrimary);
|
||||
if (idx > 0)
|
||||
m_screens.swap(0, idx);
|
||||
QXcbIntegration::instance()->setPrimaryScreen(newPrimary);
|
||||
}
|
||||
|
||||
QXcbIntegration::instance()->destroyScreen(screen);
|
||||
}
|
||||
}
|
||||
|
||||
@ -338,8 +377,7 @@ void QXcbConnection::initializeScreens()
|
||||
{
|
||||
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
|
||||
int xcbScreenNumber = 0; // screen number in the xcb sense
|
||||
QXcbScreen* primaryScreen = Q_NULLPTR;
|
||||
bool hasOutputs = false;
|
||||
QXcbScreen *primaryScreen = Q_NULLPTR;
|
||||
while (it.rem) {
|
||||
// Each "screen" in xcb terminology is a virtual desktop,
|
||||
// potentially a collection of separate juxtaposed monitors.
|
||||
@ -348,8 +386,6 @@ void QXcbConnection::initializeScreens()
|
||||
xcb_screen_t *xcbScreen = it.data;
|
||||
QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
|
||||
m_virtualDesktops.append(virtualDesktop);
|
||||
QList<QPlatformScreen *> siblings;
|
||||
int outputCount = 0;
|
||||
if (has_randr_extension) {
|
||||
xcb_generic_error_t *error = NULL;
|
||||
// RRGetScreenResourcesCurrent is fast but it may return nothing if the
|
||||
@ -366,7 +402,7 @@ void QXcbConnection::initializeScreens()
|
||||
} else {
|
||||
xcb_timestamp_t timestamp;
|
||||
xcb_randr_output_t *outputs = Q_NULLPTR;
|
||||
outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data());
|
||||
int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data());
|
||||
if (outputCount) {
|
||||
timestamp = resources_current->config_timestamp;
|
||||
outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.data());
|
||||
@ -393,6 +429,7 @@ void QXcbConnection::initializeScreens()
|
||||
qWarning("failed to get the primary output of the screen");
|
||||
free(error);
|
||||
} else {
|
||||
QList<QPlatformScreen *> siblings;
|
||||
for (int i = 0; i < outputCount; i++) {
|
||||
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output(
|
||||
xcb_randr_get_output_info_reply(xcb_connection(),
|
||||
@ -416,9 +453,8 @@ void QXcbConnection::initializeScreens()
|
||||
continue;
|
||||
}
|
||||
|
||||
QXcbScreen *screen = createScreen(virtualDesktop, outputs[i], output.data());
|
||||
QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.data());
|
||||
siblings << screen;
|
||||
hasOutputs = true;
|
||||
m_screens << screen;
|
||||
|
||||
// There can be multiple outputs per screen, use either
|
||||
@ -435,11 +471,23 @@ void QXcbConnection::initializeScreens()
|
||||
}
|
||||
}
|
||||
}
|
||||
virtualDesktop->setScreens(siblings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
virtualDesktop->setScreens(siblings);
|
||||
if (virtualDesktop->screens().isEmpty()) {
|
||||
// If there are no XRandR outputs or XRandR extension is missing,
|
||||
// then create a fake/legacy screen.
|
||||
QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, XCB_NONE, Q_NULLPTR);
|
||||
qCDebug(lcQpaScreen) << "created fake screen" << screen;
|
||||
m_screens << screen;
|
||||
if (m_primaryScreenNumber == xcbScreenNumber) {
|
||||
primaryScreen = screen;
|
||||
primaryScreen->setPrimary(true);
|
||||
}
|
||||
virtualDesktop->addScreen(screen);
|
||||
}
|
||||
xcb_screen_next(&it);
|
||||
++xcbScreenNumber;
|
||||
} // for each xcb screen
|
||||
@ -447,39 +495,25 @@ void QXcbConnection::initializeScreens()
|
||||
foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops)
|
||||
virtualDesktop->subscribeToXFixesSelectionNotify();
|
||||
|
||||
// If there's no randr extension, or there was some error above, or we found a
|
||||
// screen which doesn't have outputs for some other reason (e.g. on VNC or ssh -X),
|
||||
// but the dimensions are known anyway, and we don't already have any lingering
|
||||
// (possibly disconnected) screens, then showing windows should be possible,
|
||||
// so create one screen. (QTBUG-31389)
|
||||
QXcbVirtualDesktop *virtualDesktop = m_virtualDesktops.value(0);
|
||||
if (virtualDesktop && !hasOutputs && !virtualDesktop->size().isEmpty() && m_screens.isEmpty()) {
|
||||
QXcbScreen *screen = createScreen(virtualDesktop, 0, Q_NULLPTR);
|
||||
virtualDesktop->setScreens(QList<QPlatformScreen *>() << screen);
|
||||
m_screens << screen;
|
||||
primaryScreen = screen;
|
||||
primaryScreen->setPrimary(true);
|
||||
qCDebug(lcQpaScreen) << "found a screen with zero outputs" << screen;
|
||||
}
|
||||
|
||||
// Ensure the primary screen is first in the list
|
||||
if (primaryScreen) {
|
||||
Q_ASSERT(!m_screens.isEmpty());
|
||||
if (m_screens.first() != primaryScreen) {
|
||||
m_screens.removeOne(primaryScreen);
|
||||
m_screens.prepend(primaryScreen);
|
||||
if (m_virtualDesktops.isEmpty()) {
|
||||
qFatal("QXcbConnection: no screens available");
|
||||
} else {
|
||||
// Ensure the primary screen is first on the list
|
||||
if (primaryScreen) {
|
||||
if (m_screens.first() != primaryScreen) {
|
||||
m_screens.removeOne(primaryScreen);
|
||||
m_screens.prepend(primaryScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Push the screens to QApplication
|
||||
QXcbIntegration *integration = QXcbIntegration::instance();
|
||||
foreach (QXcbScreen* screen, m_screens) {
|
||||
qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ')';
|
||||
integration->screenAdded(screen, screen->isPrimary());
|
||||
}
|
||||
// Push the screens to QGuiApplication
|
||||
foreach (QXcbScreen *screen, m_screens) {
|
||||
qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")";
|
||||
QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
|
||||
}
|
||||
|
||||
if (!m_screens.isEmpty())
|
||||
qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
|
||||
}
|
||||
}
|
||||
|
||||
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName)
|
||||
@ -553,9 +587,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
|
||||
initializeXFixes();
|
||||
initializeScreens();
|
||||
|
||||
if (Q_UNLIKELY(m_screens.isEmpty()))
|
||||
qFatal("QXcbConnection: no screens available");
|
||||
|
||||
initializeXRender();
|
||||
m_xi2Enabled = false;
|
||||
#if defined(XCB_USE_XINPUT2)
|
||||
|
@ -518,15 +518,17 @@ private:
|
||||
void initializeXShape();
|
||||
void initializeXKB();
|
||||
void handleClientMessageEvent(const xcb_client_message_event_t *event);
|
||||
QXcbScreen* createScreen(QXcbVirtualDesktop *virtualDesktop,
|
||||
xcb_randr_output_t outputId = XCB_NONE,
|
||||
xcb_randr_get_output_info_reply_t *output = 0);
|
||||
QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc);
|
||||
QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output);
|
||||
QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow);
|
||||
bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
|
||||
void initializeScreens();
|
||||
void updateScreens(const xcb_randr_notify_event_t *event);
|
||||
bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
|
||||
void updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange);
|
||||
QXcbScreen *createScreen(QXcbVirtualDesktop *virtualDesktop,
|
||||
const xcb_randr_output_change_t &outputChange,
|
||||
xcb_randr_get_output_info_reply_t *outputInfo);
|
||||
void destroyScreen(QXcbScreen *screen);
|
||||
void initializeScreens();
|
||||
bool compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const;
|
||||
|
||||
bool m_xi2Enabled;
|
||||
|
@ -406,6 +406,9 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
|
||||
#endif // XCB_USE_XINPUT22
|
||||
case XIValuatorClass: {
|
||||
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
|
||||
// Some devices (mice) report a resolution of 0; they will be excluded later,
|
||||
// for now just prevent a division by zero
|
||||
const int vciResolution = vci->resolution ? vci->resolution : 1;
|
||||
if (vci->label == atom(QXcbAtom::AbsMTPositionX))
|
||||
caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition;
|
||||
else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor))
|
||||
@ -414,16 +417,16 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
|
||||
caps |= QTouchDevice::Pressure;
|
||||
else if (vci->label == atom(QXcbAtom::RelX)) {
|
||||
hasRelativeCoords = true;
|
||||
dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution);
|
||||
dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
|
||||
} else if (vci->label == atom(QXcbAtom::RelY)) {
|
||||
hasRelativeCoords = true;
|
||||
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
|
||||
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
|
||||
} else if (vci->label == atom(QXcbAtom::AbsX)) {
|
||||
caps |= QTouchDevice::Position;
|
||||
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
|
||||
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
|
||||
} else if (vci->label == atom(QXcbAtom::AbsY)) {
|
||||
caps |= QTouchDevice::Position;
|
||||
dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution);
|
||||
dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -81,6 +81,13 @@ void QXcbVirtualDesktop::addScreen(QPlatformScreen *s)
|
||||
((QXcbScreen *) s)->isPrimary() ? m_screens.prepend(s) : m_screens.append(s);
|
||||
}
|
||||
|
||||
void QXcbVirtualDesktop::setPrimaryScreen(QPlatformScreen *s)
|
||||
{
|
||||
const int idx = m_screens.indexOf(s);
|
||||
Q_ASSERT(idx > -1);
|
||||
m_screens.swap(0, idx);
|
||||
}
|
||||
|
||||
QXcbXSettings *QXcbVirtualDesktop::xSettings() const
|
||||
{
|
||||
if (!m_xSettings) {
|
||||
@ -149,16 +156,15 @@ void QXcbVirtualDesktop::updateWorkArea()
|
||||
}
|
||||
|
||||
QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
|
||||
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
|
||||
QString outputName)
|
||||
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output)
|
||||
: QXcbObject(connection)
|
||||
, m_virtualDesktop(virtualDesktop)
|
||||
, m_output(outputId)
|
||||
, m_crtc(output ? output->crtc : 0)
|
||||
, m_crtc(output ? output->crtc : XCB_NONE)
|
||||
, m_mode(XCB_NONE)
|
||||
, m_primary(false)
|
||||
, m_rotation(XCB_RANDR_ROTATION_ROTATE_0)
|
||||
, m_outputName(outputName)
|
||||
, m_outputName(getOutputName(output))
|
||||
, m_outputSizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize())
|
||||
, m_virtualSize(virtualDesktop->size())
|
||||
, m_virtualSizeMillimeters(virtualDesktop->physicalSize())
|
||||
@ -266,6 +272,22 @@ QXcbScreen::~QXcbScreen()
|
||||
delete m_cursor;
|
||||
}
|
||||
|
||||
QString QXcbScreen::getOutputName(xcb_randr_get_output_info_reply_t *outputInfo)
|
||||
{
|
||||
QString name;
|
||||
if (outputInfo) {
|
||||
name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(outputInfo),
|
||||
xcb_randr_get_output_info_name_length(outputInfo));
|
||||
} else {
|
||||
QByteArray displayName = connection()->displayName();
|
||||
int dotPos = displayName.lastIndexOf('.');
|
||||
if (dotPos != -1)
|
||||
displayName.truncate(dotPos);
|
||||
name = QString::fromLocal8Bit(displayName) + QLatin1Char('.')
|
||||
+ QString::number(m_virtualDesktop->number());
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
|
||||
{
|
||||
@ -390,6 +412,16 @@ QPlatformCursor *QXcbScreen::cursor() const
|
||||
return m_cursor;
|
||||
}
|
||||
|
||||
void QXcbScreen::setOutput(xcb_randr_output_t outputId,
|
||||
xcb_randr_get_output_info_reply_t *outputInfo)
|
||||
{
|
||||
m_output = outputId;
|
||||
m_crtc = outputInfo ? outputInfo->crtc : XCB_NONE;
|
||||
m_mode = XCB_NONE;
|
||||
m_outputName = getOutputName(outputInfo);
|
||||
// TODO: Send an event to the QScreen instance that the screen changed its name
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief handle the XCB screen change event and update properties
|
||||
|
||||
@ -458,19 +490,10 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan
|
||||
|
||||
updateGeometry(change_event->timestamp);
|
||||
|
||||
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
|
||||
QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), m_orientation);
|
||||
|
||||
QDpi ldpi = logicalDpi();
|
||||
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QPlatformScreen::screen(), ldpi.first, ldpi.second);
|
||||
|
||||
// Windows which had null screens have already had expose events by now.
|
||||
// They need to be told the screen is back, it's OK to render.
|
||||
foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
|
||||
QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle());
|
||||
if (xcbWin)
|
||||
xcbWin->maybeSetScreen(this);
|
||||
}
|
||||
}
|
||||
|
||||
void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
|
||||
|
@ -72,6 +72,7 @@ public:
|
||||
void setScreens(QList<QPlatformScreen *> sl) { m_screens = sl; }
|
||||
void removeScreen(QPlatformScreen *s) { m_screens.removeOne(s); }
|
||||
void addScreen(QPlatformScreen *s);
|
||||
void setPrimaryScreen(QPlatformScreen *s);
|
||||
|
||||
QXcbXSettings *xSettings() const;
|
||||
|
||||
@ -101,10 +102,11 @@ class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen
|
||||
{
|
||||
public:
|
||||
QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
|
||||
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
|
||||
QString outputName);
|
||||
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *outputInfo);
|
||||
~QXcbScreen();
|
||||
|
||||
QString getOutputName(xcb_randr_get_output_info_reply_t *outputInfo);
|
||||
|
||||
QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
|
||||
|
||||
QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE;
|
||||
@ -137,6 +139,10 @@ public:
|
||||
xcb_randr_crtc_t crtc() const { return m_crtc; }
|
||||
xcb_randr_mode_t mode() const { return m_mode; }
|
||||
|
||||
void setOutput(xcb_randr_output_t outputId,
|
||||
xcb_randr_get_output_info_reply_t *outputInfo);
|
||||
void setCrtc(xcb_randr_crtc_t crtc) { m_crtc = crtc; }
|
||||
|
||||
void windowShown(QXcbWindow *window);
|
||||
QString windowManagerName() const { return m_windowManagerName; }
|
||||
bool syncRequestSupported() const { return m_syncRequestSupported; }
|
||||
|
@ -143,7 +143,7 @@ const quint32 XEMBED_VERSION = 0;
|
||||
|
||||
QXcbScreen *QXcbWindow::parentScreen()
|
||||
{
|
||||
return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : m_xcbScreen;
|
||||
return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : xcbScreen();
|
||||
}
|
||||
|
||||
// Returns \c true if we should set WM_TRANSIENT_FOR on \a w
|
||||
@ -266,7 +266,6 @@ static const char *wm_window_type_property_id = "_q_xcb_wm_window_type";
|
||||
QXcbWindow::QXcbWindow(QWindow *window)
|
||||
: QPlatformWindow(window)
|
||||
, m_window(0)
|
||||
, m_xcbScreen(0)
|
||||
, m_syncCounter(0)
|
||||
, m_gravity(XCB_GRAVITY_STATIC)
|
||||
, m_mapped(false)
|
||||
@ -322,7 +321,6 @@ void QXcbWindow::create()
|
||||
QRect rect = windowGeometry();
|
||||
QXcbScreen *platformScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
|
||||
|
||||
m_xcbScreen = platformScreen;
|
||||
if (type == Qt::Desktop) {
|
||||
m_window = platformScreen->root();
|
||||
m_depth = platformScreen->screen()->root_depth;
|
||||
@ -624,27 +622,18 @@ void QXcbWindow::destroy()
|
||||
m_pendingSyncRequest->invalidate();
|
||||
}
|
||||
|
||||
void QXcbWindow::maybeSetScreen(QXcbScreen *screen)
|
||||
{
|
||||
if (!window()->screen() && screen->geometry().contains(geometry().topLeft())) {
|
||||
QWindowSystemInterface::handleWindowScreenChanged(window(), static_cast<QPlatformScreen *>(screen)->screen());
|
||||
QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(0, 0), window()->size())));
|
||||
}
|
||||
}
|
||||
|
||||
void QXcbWindow::setGeometry(const QRect &rect)
|
||||
{
|
||||
QPlatformWindow::setGeometry(rect);
|
||||
|
||||
propagateSizeHints();
|
||||
|
||||
QXcbScreen *currentScreen = m_xcbScreen;
|
||||
QXcbScreen *currentScreen = xcbScreen();
|
||||
QXcbScreen *newScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
|
||||
|
||||
if (!newScreen)
|
||||
newScreen = xcbScreen();
|
||||
|
||||
m_xcbScreen = newScreen;
|
||||
const QRect wmGeometry = windowToWmGeometry(rect);
|
||||
|
||||
if (newScreen && newScreen != currentScreen)
|
||||
@ -848,15 +837,13 @@ void QXcbWindow::hide()
|
||||
Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window));
|
||||
|
||||
// send synthetic UnmapNotify event according to icccm 4.1.4
|
||||
if (xcbScreen()) {
|
||||
xcb_unmap_notify_event_t event;
|
||||
event.response_type = XCB_UNMAP_NOTIFY;
|
||||
event.event = xcbScreen()->root();
|
||||
event.window = m_window;
|
||||
event.from_configure = false;
|
||||
Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(),
|
||||
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
|
||||
}
|
||||
xcb_unmap_notify_event_t event;
|
||||
event.response_type = XCB_UNMAP_NOTIFY;
|
||||
event.event = xcbScreen()->root();
|
||||
event.window = m_window;
|
||||
event.from_configure = false;
|
||||
Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(),
|
||||
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
|
||||
|
||||
xcb_flush(xcb_connection());
|
||||
|
||||
@ -1185,8 +1172,6 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
|
||||
event.data.data32[3] = 0;
|
||||
event.data.data32[4] = 0;
|
||||
|
||||
if (!xcbScreen())
|
||||
return;
|
||||
Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
|
||||
}
|
||||
|
||||
@ -1448,8 +1433,6 @@ void QXcbWindow::setParent(const QPlatformWindow *parent)
|
||||
xcb_parent_id = qXcbParent->xcb_window();
|
||||
m_embedded = qXcbParent->window()->type() == Qt::ForeignWindow;
|
||||
} else {
|
||||
if (!xcbScreen())
|
||||
return;
|
||||
xcb_parent_id = xcbScreen()->root();
|
||||
m_embedded = false;
|
||||
}
|
||||
@ -2005,7 +1988,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
|
||||
{
|
||||
bool fromSendEvent = (event->response_type & 0x80);
|
||||
QPoint pos(event->x, event->y);
|
||||
if (!parent() && !fromSendEvent && xcbScreen()) {
|
||||
if (!parent() && !fromSendEvent) {
|
||||
// Do not trust the position, query it instead.
|
||||
xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(),
|
||||
xcbScreen()->root(), 0, 0);
|
||||
@ -2017,21 +2000,38 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
|
||||
}
|
||||
}
|
||||
|
||||
const QRect rect = QRect(pos, QSize(event->width, event->height));
|
||||
QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(rect);
|
||||
// The original geometry requested by setGeometry() might be different
|
||||
// from what we end up with after applying window constraints.
|
||||
QRect requestedGeometry = geometry();
|
||||
|
||||
QXcbScreen *currentScreen = m_xcbScreen;
|
||||
m_xcbScreen = static_cast<QXcbScreen*>(newScreen);
|
||||
const QRect actualGeometry = QRect(pos, QSize(event->width, event->height));
|
||||
QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(actualGeometry);
|
||||
if (!newScreen)
|
||||
return;
|
||||
|
||||
QPlatformWindow::setGeometry(rect);
|
||||
QWindowSystemInterface::handleGeometryChange(window(), rect);
|
||||
if (newScreen != currentScreen)
|
||||
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
|
||||
// Persist the actual geometry so that QWindow::geometry() can
|
||||
// be queried in the resize event.
|
||||
QPlatformWindow::setGeometry(actualGeometry);
|
||||
|
||||
if (m_mapped)
|
||||
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
|
||||
// FIXME: In the case of the requestedGeometry not matching the actualGeometry due
|
||||
// to e.g. the window manager applying restrictions to the geometry, the application
|
||||
// will never see a move/resize event if the actualGeometry is the same as the current
|
||||
// geometry, and may think the requested geometry was fulfilled.
|
||||
QWindowSystemInterface::handleGeometryChange(window(), actualGeometry);
|
||||
|
||||
// QPlatformScreen::screen() is updated asynchronously, so we can't compare it
|
||||
// with the newScreen. Just send the WindowScreenChanged event and QGuiApplication
|
||||
// will make the comparison later.
|
||||
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
|
||||
|
||||
// For expose events we have no way of telling QGuiApplication to used the locally
|
||||
// cached version of the previous state, so we may in some situations end up with
|
||||
// an additional expose event.
|
||||
QRect previousGeometry = requestedGeometry != actualGeometry ?
|
||||
requestedGeometry : qt_window_private(window())->geometry;
|
||||
|
||||
if (m_mapped && actualGeometry.size() != previousGeometry.size())
|
||||
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), actualGeometry.size()));
|
||||
|
||||
if (m_usingSyncProtocol && m_syncState == SyncReceived)
|
||||
m_syncState = SyncAndConfigureReceived;
|
||||
@ -2298,8 +2298,6 @@ void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
|
||||
return;
|
||||
|
||||
const QPoint local(event->event_x, event->event_y);
|
||||
if (!xcbScreen())
|
||||
return;
|
||||
QPoint global = QPoint(event->root_x, event->root_y);
|
||||
QWindowSystemInterface::handleEnterEvent(window(), local, global);
|
||||
}
|
||||
@ -2317,8 +2315,6 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
|
||||
|
||||
if (enterWindow) {
|
||||
QPoint local(enter->event_x, enter->event_y);
|
||||
if (!xcbScreen())
|
||||
return;
|
||||
QPoint global = QPoint(event->root_x, event->root_y);
|
||||
|
||||
QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global);
|
||||
@ -2334,8 +2330,6 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
|
||||
connection()->setTime(event->time);
|
||||
|
||||
const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
|
||||
if (!xcbScreen())
|
||||
return;
|
||||
|
||||
if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
|
||||
if (propertyDeleted)
|
||||
@ -2655,8 +2649,6 @@ bool QXcbWindow::needsSync() const
|
||||
|
||||
void QXcbWindow::postSyncWindowRequest()
|
||||
{
|
||||
if (!xcbScreen())
|
||||
return;
|
||||
if (!m_pendingSyncRequest) {
|
||||
QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this);
|
||||
m_pendingSyncRequest = e;
|
||||
|
@ -167,7 +167,6 @@ public:
|
||||
|
||||
virtual void create();
|
||||
virtual void destroy();
|
||||
void maybeSetScreen(QXcbScreen *screen);
|
||||
QXcbScreen *screenForNativeGeometry(const QRect &newGeometry) const;
|
||||
|
||||
public Q_SLOTS:
|
||||
@ -215,8 +214,6 @@ protected:
|
||||
|
||||
xcb_window_t m_window;
|
||||
|
||||
QXcbScreen *m_xcbScreen;
|
||||
|
||||
uint m_depth;
|
||||
QImage::Format m_imageFormat;
|
||||
bool m_imageRgbSwap;
|
||||
|
@ -3795,7 +3795,7 @@ bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) {
|
||||
Q_Q(QFileDialog);
|
||||
|
||||
if (event->matches(QKeySequence::Cancel)) {
|
||||
q->hide();
|
||||
q->reject();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -198,13 +198,14 @@ QFileInfo QFileSystemModel::fileInfo(const QModelIndex &index) const
|
||||
bool QFileSystemModel::remove(const QModelIndex &aindex)
|
||||
{
|
||||
const QString path = filePath(aindex);
|
||||
const bool success = QFileInfo(path).isFile() ? QFile::remove(path) : QDir(path).removeRecursively();
|
||||
#ifndef QT_NO_FILESYSTEMWATCHER
|
||||
QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
|
||||
d->fileInfoGatherer.removePath(path);
|
||||
if (success) {
|
||||
QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
|
||||
d->fileInfoGatherer.removePath(path);
|
||||
}
|
||||
#endif
|
||||
if (QFileInfo(path).isFile())
|
||||
return QFile::remove(path);
|
||||
return QDir(path).removeRecursively();
|
||||
return success;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1620,11 +1621,14 @@ bool QFileSystemModel::event(QEvent *event)
|
||||
bool QFileSystemModel::rmdir(const QModelIndex &aindex)
|
||||
{
|
||||
QString path = filePath(aindex);
|
||||
const bool success = QDir().rmdir(path);
|
||||
#ifndef QT_NO_FILESYSTEMWATCHER
|
||||
QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
|
||||
d->fileInfoGatherer.removePath(path);
|
||||
if (success) {
|
||||
QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
|
||||
d->fileInfoGatherer.removePath(path);
|
||||
}
|
||||
#endif
|
||||
return QDir().rmdir(path);
|
||||
return success;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1800,10 +1804,6 @@ void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path, const QV
|
||||
node->fileName = fileName;
|
||||
}
|
||||
|
||||
if (info.size() == -1 && !info.isSymLink()) {
|
||||
removeNode(parentNode, fileName);
|
||||
continue;
|
||||
}
|
||||
if (*node != info ) {
|
||||
node->populate(info);
|
||||
bypassFilters.remove(node);
|
||||
|
@ -76,7 +76,7 @@
|
||||
advises against will produce more easily comprehensible software.
|
||||
Doing what it tells you to do may also help.
|
||||
|
||||
\b{\l{http://www.amazon.com/exec/obidos/ASIN/047159900X/trolltech/t}{The
|
||||
\b{\l{http://www.amazon.com/New-Windows-Interface-Microsoft-Press/dp/1556156790/}{The
|
||||
Microsoft Windows User Experience}}, ISBN 1-55615-679-0,
|
||||
is Microsoft's look and feel bible. Indispensable for everyone who
|
||||
has customers that worship Microsoft, and it's quite good, too.
|
||||
|
@ -1262,7 +1262,7 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
|
||||
activated when the user clicks or double clicks on it, depending on the
|
||||
system configuration. It is also activated when the user presses the
|
||||
activation key (on Windows and X11 this is the \uicontrol Return key, on Mac OS
|
||||
X it is \uicontrol{Ctrl+0}).
|
||||
X it is \uicontrol{Command+O}).
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
@ -255,7 +255,7 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
|
||||
\value TextHeuristicRole This action should be put in the application menu based on the action's text
|
||||
as described in the QMenuBar documentation.
|
||||
\value ApplicationSpecificRole This action should be put in the application menu with an application specific role
|
||||
\value AboutQtRole This action matches handles the "About Qt" menu item.
|
||||
\value AboutQtRole This action handles the "About Qt" menu item.
|
||||
\value AboutRole This action should be placed where the "About" menu item is in the application menu. The text of
|
||||
the menu item will be set to "About <application name>". The application name is fetched from the
|
||||
\c{Info.plist} file in the application's bundle (See \l{Qt for OS X - Deployment}).
|
||||
@ -1231,7 +1231,7 @@ void QAction::activate(ActionEvent event)
|
||||
\since 4.2
|
||||
|
||||
This indicates what role the action serves in the application menu on Mac
|
||||
OS X. By default all action have the TextHeuristicRole, which means that
|
||||
OS X. By default all actions have the TextHeuristicRole, which means that
|
||||
the action is added based on its text (see QMenuBar for more information).
|
||||
|
||||
The menu role can only be changed before the actions are put into the menu
|
||||
|
@ -448,6 +448,26 @@ void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTi
|
||||
if (!widget)
|
||||
return;
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
// Having every repaint() leading to a sync/flush is bad as it causes
|
||||
// compositing and waiting for vsync each and every time. Change to
|
||||
// UpdateLater, except for approx. once per frame to prevent starvation in
|
||||
// case the control does not get back to the event loop.
|
||||
QWidget *w = widget->window();
|
||||
if (updateTime == UpdateNow && w && w->windowHandle() && QWindowPrivate::get(w->windowHandle())->compositing) {
|
||||
int refresh = 60;
|
||||
QScreen *ws = w->windowHandle()->screen();
|
||||
if (ws)
|
||||
refresh = ws->refreshRate();
|
||||
QWindowPrivate *wd = QWindowPrivate::get(w->windowHandle());
|
||||
if (wd->lastComposeTime.isValid()) {
|
||||
const qint64 elapsed = wd->lastComposeTime.elapsed();
|
||||
if (elapsed <= qint64(1000.0f / refresh))
|
||||
updateTime = UpdateLater;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (updateTime) {
|
||||
case UpdateLater:
|
||||
updateRequestSent = true;
|
||||
@ -621,7 +641,11 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget,
|
||||
|
||||
|
||||
const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
|
||||
const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint())));
|
||||
QRect translatedRect = widgetRect;
|
||||
if (widget != tlw)
|
||||
translatedRect.translate(widget->mapTo(tlw, QPoint()));
|
||||
// Graphics effects may exceed window size, clamp.
|
||||
translatedRect = translatedRect.intersected(QRect(QPoint(), tlw->size()));
|
||||
if (qt_region_strictContains(dirty, translatedRect)) {
|
||||
if (updateTime == UpdateNow)
|
||||
sendUpdateRequest(tlw, updateTime);
|
||||
|
@ -1816,7 +1816,8 @@ void QDockAreaLayoutInfo::saveState(QDataStream &stream) const
|
||||
stream << flags;
|
||||
|
||||
if (w->isWindow()) {
|
||||
stream << w->x() << w->y() << w->width() << w->height();
|
||||
const QRect geometry = w->geometry();
|
||||
stream << geometry.x() << geometry.y() << geometry.width() << geometry.height();
|
||||
} else {
|
||||
stream << item.pos << item.size << pick(o, item.minimumSize())
|
||||
<< pick(o, item.maximumSize());
|
||||
|
@ -1093,14 +1093,8 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
|
||||
q->setWindowFlags(flags);
|
||||
|
||||
|
||||
if (!rect.isNull()) {
|
||||
if (floating) {
|
||||
q->resize(rect.size());
|
||||
q->move(rect.topLeft());
|
||||
} else {
|
||||
if (!rect.isNull())
|
||||
q->setGeometry(rect);
|
||||
}
|
||||
}
|
||||
|
||||
updateButtons();
|
||||
|
||||
|
@ -140,6 +140,8 @@ public:
|
||||
|
||||
hr = applicationFactory->CreateInstance(this, &base, &core);
|
||||
RETURN_VOID_IF_FAILED("Failed to create application container instance");
|
||||
|
||||
pidFile = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
~AppContainer()
|
||||
@ -157,6 +159,13 @@ public:
|
||||
int argc = app->args.count();
|
||||
char **argv = app->args.data();
|
||||
const int res = main(argc, argv);
|
||||
if (app->pidFile != INVALID_HANDLE_VALUE) {
|
||||
const QByteArray resString = QByteArray::number(res);
|
||||
WriteFile(app->pidFile, reinterpret_cast<LPCVOID>(resString.constData()),
|
||||
resString.size(), NULL, NULL);
|
||||
FlushFileBuffers(app->pidFile);
|
||||
CloseHandle(app->pidFile);
|
||||
}
|
||||
app->core->Exit();
|
||||
return res;
|
||||
}, this, CREATE_SUSPENDED, nullptr);
|
||||
@ -234,6 +243,9 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (args.count() >= 2 && strncmp(args.at(1), "-ServerName:", 12) == 0)
|
||||
args.remove(1);
|
||||
|
||||
bool develMode = false;
|
||||
bool debugWait = false;
|
||||
foreach (const char *arg, args) {
|
||||
@ -248,11 +260,10 @@ private:
|
||||
.absoluteFilePath(QString::number(uint(GetCurrentProcessId())) + QStringLiteral(".pid"));
|
||||
CREATEFILE2_EXTENDED_PARAMETERS params = {
|
||||
sizeof(CREATEFILE2_EXTENDED_PARAMETERS),
|
||||
FILE_ATTRIBUTE_NORMAL, FILE_FLAG_DELETE_ON_CLOSE
|
||||
FILE_ATTRIBUTE_NORMAL
|
||||
};
|
||||
// (Unused) handle will automatically be closed when the app exits
|
||||
CreateFile2(reinterpret_cast<LPCWSTR>(pidFileName.utf16()),
|
||||
0, FILE_SHARE_READ|FILE_SHARE_DELETE, CREATE_ALWAYS, ¶ms);
|
||||
pidFile = CreateFile2(reinterpret_cast<LPCWSTR>(pidFileName.utf16()),
|
||||
GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS, ¶ms);
|
||||
// Install the develMode message handler
|
||||
#ifndef Q_OS_WINPHONE
|
||||
defaultMessageHandler = qInstallMessageHandler(devMessageHandler);
|
||||
@ -315,6 +326,7 @@ private:
|
||||
QByteArray commandLine;
|
||||
QVarLengthArray<char *> args;
|
||||
HANDLE mainThread;
|
||||
HANDLE pidFile;
|
||||
};
|
||||
|
||||
// Main entry point for Appx containers
|
||||
|
@ -1,6 +1,6 @@
|
||||
TEMPLATE = subdirs
|
||||
CONFIG += ordered
|
||||
|
||||
SUBDIRS += \
|
||||
app \
|
||||
test
|
||||
!winrt: SUBDIRS += app
|
||||
|
||||
SUBDIRS += test
|
||||
|
@ -7,5 +7,5 @@ QT = core testlib
|
||||
SOURCES = ../tst_qlogging.cpp
|
||||
|
||||
DEFINES += QT_MESSAGELOGCONTEXT
|
||||
TEST_HELPER_INSTALLS = ../app/app
|
||||
!winrt: TEST_HELPER_INSTALLS = ../app/app
|
||||
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
|
||||
|
@ -1,2 +1,3 @@
|
||||
[isWritable:native]
|
||||
osx-10.10
|
||||
osx-10.11
|
||||
|
@ -2729,7 +2729,7 @@ void tst_QTextStream::readBomSeekBackReadBomAgain()
|
||||
QFile::remove("utf8bom");
|
||||
QFile file("utf8bom");
|
||||
QVERIFY(file.open(QFile::ReadWrite));
|
||||
file.write("\xef\xbb\xbf" "Andreas");
|
||||
file.write("\xef\xbb\xbf""Andreas");
|
||||
file.seek(0);
|
||||
QCOMPARE(file.pos(), qint64(0));
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
TEMPLATE = subdirs
|
||||
CONFIG += ordered
|
||||
|
||||
SUBDIRS += \
|
||||
signalbug \
|
||||
test
|
||||
!winrt: SUBDIRS+= signalbug
|
||||
|
||||
SUBDIRS += test
|
||||
|
@ -3,5 +3,5 @@ TARGET = ../tst_qobject
|
||||
QT = core-private network testlib
|
||||
SOURCES = ../tst_qobject.cpp
|
||||
|
||||
TEST_HELPER_INSTALLS = ../signalbug/signalbug
|
||||
!winrt: TEST_HELPER_INSTALLS = ../signalbug/signalbug
|
||||
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
|
||||
|
@ -2,6 +2,7 @@
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
|
||||
** Copyright (C) 2015 Intel Corporation.
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
@ -2516,14 +2517,26 @@ void tst_QVariant::variantMap()
|
||||
|
||||
QVariant v = map;
|
||||
QVariantMap map2 = qvariant_cast<QVariantMap>(v);
|
||||
|
||||
QCOMPARE(map2.value("test").toInt(), 42);
|
||||
QCOMPARE(map2, map);
|
||||
|
||||
map2 = v.toMap();
|
||||
QCOMPARE(map2.value("test").toInt(), 42);
|
||||
QCOMPARE(map2, map);
|
||||
|
||||
QVariant v2 = QVariant(QMetaType::type("QVariantMap"), &map);
|
||||
QCOMPARE(qvariant_cast<QVariantMap>(v2).value("test").toInt(), 42);
|
||||
|
||||
QVariant v3 = QVariant(QMetaType::type("QMap<QString, QVariant>"), &map);
|
||||
QCOMPARE(qvariant_cast<QVariantMap>(v3).value("test").toInt(), 42);
|
||||
|
||||
// multi-keys
|
||||
map.insertMulti("test", 47);
|
||||
v = map;
|
||||
map2 = qvariant_cast<QVariantMap>(v);
|
||||
QCOMPARE(map2, map);
|
||||
map2 = v.toMap();
|
||||
QCOMPARE(map2, map);
|
||||
}
|
||||
|
||||
void tst_QVariant::variantHash()
|
||||
@ -2533,14 +2546,26 @@ void tst_QVariant::variantHash()
|
||||
|
||||
QVariant v = hash;
|
||||
QVariantHash hash2 = qvariant_cast<QVariantHash>(v);
|
||||
|
||||
QCOMPARE(hash2.value("test").toInt(), 42);
|
||||
QCOMPARE(hash2, hash);
|
||||
|
||||
hash2 = v.toHash();
|
||||
QCOMPARE(hash2.value("test").toInt(), 42);
|
||||
QCOMPARE(hash2, hash);
|
||||
|
||||
QVariant v2 = QVariant(QMetaType::type("QVariantHash"), &hash);
|
||||
QCOMPARE(qvariant_cast<QVariantHash>(v2).value("test").toInt(), 42);
|
||||
|
||||
QVariant v3 = QVariant(QMetaType::type("QHash<QString, QVariant>"), &hash);
|
||||
QCOMPARE(qvariant_cast<QVariantHash>(v3).value("test").toInt(), 42);
|
||||
|
||||
// multi-keys
|
||||
hash.insertMulti("test", 47);
|
||||
v = hash;
|
||||
hash2 = qvariant_cast<QVariantHash>(v);
|
||||
QCOMPARE(hash2, hash);
|
||||
hash2 = v.toHash();
|
||||
QCOMPARE(hash2, hash);
|
||||
}
|
||||
|
||||
class CustomQObject : public QObject {
|
||||
@ -3258,24 +3283,40 @@ void tst_QVariant::convertIterables() const
|
||||
map.insert("3", 4);
|
||||
QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
|
||||
QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
|
||||
|
||||
map.insertMulti("3", 5);
|
||||
QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
|
||||
QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
|
||||
}
|
||||
{
|
||||
QVariantMap map;
|
||||
map.insert("3", 4);
|
||||
QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
|
||||
QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
|
||||
|
||||
map.insertMulti("3", 5);
|
||||
QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
|
||||
QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
|
||||
}
|
||||
{
|
||||
QHash<QString, int> hash;
|
||||
hash.insert("3", 4);
|
||||
QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
|
||||
QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
|
||||
|
||||
hash.insertMulti("3", 5);
|
||||
QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
|
||||
QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
|
||||
}
|
||||
{
|
||||
QVariantHash hash;
|
||||
hash.insert("3", 4);
|
||||
QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
|
||||
QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
|
||||
|
||||
hash.insertMulti("3", 5);
|
||||
QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
|
||||
QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS = \
|
||||
crashonexit \
|
||||
test
|
||||
|
||||
!winrt: SUBDIRS += crashonexit
|
||||
|
||||
CONFIG += ordered
|
||||
|
@ -5,5 +5,5 @@ CONFIG += console
|
||||
QT = core testlib
|
||||
SOURCES = ../tst_qthreadstorage.cpp
|
||||
|
||||
TEST_HELPER_INSTALLS = ../crashonexit/crashonexit
|
||||
!winrt: TEST_HELPER_INSTALLS = ../crashonexit/crashonexit
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += test \
|
||||
syslocaleapp
|
||||
SUBDIRS += test
|
||||
!winrt: SUBDIRS+=syslocaleapp
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user