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

Conflicts:
	src/android/templates/AndroidManifest.xml
	tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp

Change-Id: I4c9679e3a8ebba118fbf4772301ff8fde60455b9
This commit is contained in:
Liang Qi 2019-01-26 08:35:40 +01:00
commit 980567b3a3
128 changed files with 104797 additions and 1049 deletions

167
dist/changes-5.12.1 vendored Normal file
View File

@ -0,0 +1,167 @@
Qt 5.12.1 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.12.0.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
http://doc.qt.io/qt-5/index.html
The Qt version 5.12 series is binary compatible with the 5.11.x series.
Applications compiled for 5.11 will continue to run with 5.12.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Important Behavior Changes *
****************************************************************************
- qmake / WinRT:
* Cross-builds will now ignore pre-set values of %INCLUDE% and %LIB%
when building target executables. If necessary, use configure's -I and
-L switches when building Qt, and pass QMAKE_INCDIR and QMAKE_LIBDIR
on qmake's command line when building own projects.
****************************************************************************
* Documentation *
****************************************************************************
- Fixed the icons for the "file save" action that were inaccurate
representations of a 3.5-inch floppy disk (the cut edge was on the wrong
side). Now all floppy representations are physically accurate.
****************************************************************************
* QtCore *
****************************************************************************
- [QTBUG-71256] QString, QByteArray and QLocale's toDouble return an infinity
on overflow (since 5.7), while setting ok to false; this was at odds with
their documented behavior of returning 0 on failure. The documentation now
reflects the actual behavior.
- [QTBUG-71868] QString, QByteArray and QLocale's toFloat returned an
infinity on double-overflow (since 5.7) but returned 0 on a finite double
outside float's range, while setting ok to false; this was at odds with
their documented behavior of returning 0 on any failure. They also
succeeded, returning zero, on underflow of float's range, unless double
underflowed, where they failed. Changed the handling of values outside
float's range to match that of values outside double's range: fail,
returning an infinity on overflow or zero on underflow. The documentation
now reflects the revised behavior, which matches toDouble().
- QCborStreamReader:
* [QTBUG-71426] Made setDevice() clear the last error.
- QCollator:
* [QTBUG-58621] Added support for collation in the C locale, albeit this is
only well-defined for ASCII. Collation sort keys remain unsupported on
Darwin.
- QContiguousCache:
* [QTBUG-52125] Fixed a memory leak.
- QObject:
* [QTBUG-32340] Fixed a bug that caused isSignalConnected() to return
true if the signal was connected and later disconnected.
* [QTBUG-71550] Fixed a bug that caused isSignalConnected() not to
report signals that were connected by the QML engine.
- QPluginLoader:
* [QTBUG-71443] Fixed the parsing of ELF headers (Linux, FreeBSD, Solaris,
etc.), which could cause certain valid plugins to not be deteced as
valid.
- QRegularExpression:
* [QTBUG-72539] The wildcardToRegularExpression method now returns a
properly anchored pattern.
- QSettings:
* [QTBUG-72007] Fixed QSettings parsing of blank spaces after comment lines
in INI-style configuration files.
- QStringListModel:
* setData will now emit the dataChanged() signal only if the string set
is different from the one already contained in the model
- QSysInfo:
* [QTBUG-72489] Now returns "Mojave" in prettyProductName() for macOS
10.14.
- QUrl:
* [QTBUG-71973] Changed the normalization done by
QUrl::NormalizePathSegments) to match what web browsers do for non-local
URLs.
****************************************************************************
* QtGui *
****************************************************************************
- Text:
* Fixed a bug where eliding text could change the height of its bounding
rectangle for certain fonts.
* Improved appearance of monochrome text on some platforms.
* Fixed so ShowTabsAndSpaces will use the correct font.
****************************************************************************
* QtSql *
****************************************************************************
- PostgreSQL:
* Added support for PostgreSQL 11
****************************************************************************
* QtWidgets *
****************************************************************************
- Reverted a Qt 5.12.0 behavior change in QToolTip that made plain tooltip
text be wrapped automatically.
- [QTBUG-72844] Fixed a regression related to accepting a Drag'n'Drop event.
- [QTBUG-27110] Reverted a change that caused a regression related to
styling a QListView using CSS.
- QWidgetLineControl/security:
* Zero-out the string that contains a password entered into the
QLineEdit
* Preallocate a buffer for the string that contains the entered value
when the QLineEdit serves as a password input field to minimize
reallocations.
****************************************************************************
* Platform Specific Changes *
****************************************************************************
- Android:
* QClipboard now supports HTML and URI data.
- Windows:
* Reduced the number of font engines that are created when loading new
fonts, fixing crashes in some special cases where a large number of
fonts are created during a short period of time.
- X11:
* [QTBUG-71296] Fixed a bug with open/close hand cursors not being shown
correctly.
* [QTBUG-46626][QTBUG-70756] Fixed a bug with dialogs hidden by other
windows in certain use cases.
****************************************************************************
* Third-Party Code *
****************************************************************************
- [QTBUG-65503] Removed xkbcommon from bundled sources. This library is
present on all supported platforms. The minimal required version now is
0.5.0.
- Updated bundled SQLite to version 3.26.0.
****************************************************************************
* Tools *
****************************************************************************
- moc now parses enum struct the same way as enum class therefore that
keyword can be used with the Q_ENUM macro as well as Q_FLAG and
Q_DECLARE_FLAGS.

View File

@ -3,7 +3,7 @@
dita.metadata.default.author = Qt Project dita.metadata.default.author = Qt Project
dita.metadata.default.permissions = all dita.metadata.default.permissions = all
dita.metadata.default.publisher = Qt Project dita.metadata.default.publisher = Qt Project
dita.metadata.default.copyryear = 2018 dita.metadata.default.copyryear = 2019
dita.metadata.default.copyrholder = The Qt Company Ltd dita.metadata.default.copyrholder = The Qt Company Ltd
dita.metadata.default.audience = programmer dita.metadata.default.audience = programmer

View File

@ -78,7 +78,7 @@ HTML.footer += \
" <ul id=\"menu-footer-submenu\" class=\"right clearfix\"><li id=\"menu-item-1795\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-1795\"><a title=\"Sign into your account.\" href=\"https://account.qt.io/login\">Sign In</a></li>\n" \ " <ul id=\"menu-footer-submenu\" class=\"right clearfix\"><li id=\"menu-item-1795\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-1795\"><a title=\"Sign into your account.\" href=\"https://account.qt.io/login\">Sign In</a></li>\n" \
" <li id=\"menu-item-10375\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-10375\"><a href=\"mailto:feedback@theqtcompany.com?Subject=Feedback%20about%20doc.qt.io%20site\">Feedback</a></li>\n" \ " <li id=\"menu-item-10375\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-10375\"><a href=\"mailto:feedback@theqtcompany.com?Subject=Feedback%20about%20doc.qt.io%20site\">Feedback</a></li>\n" \
" <li id=\"menu-item-1494\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1494\"><a href=\"http://qt.io/contact-us/\">Contact us</a></li>\n" \ " <li id=\"menu-item-1494\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1494\"><a href=\"http://qt.io/contact-us/\">Contact us</a></li>\n" \
" <li id=\"menu-item-4472\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-4472\"><a href=\"http://qt.io/about-us/\">© 2018 The Qt Company</a></li>\n" \ " <li id=\"menu-item-4472\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-4472\"><a href=\"http://qt.io/about-us/\">© 2019 The Qt Company</a></li>\n" \
" </ul>\n" \ " </ul>\n" \
"</div>\n" \ "</div>\n" \
"</div>\n" \ "</div>\n" \

View File

@ -8,7 +8,7 @@ HTML.footer = \
"</div>\n" \ "</div>\n" \
"<div class=\"footer\">\n" \ "<div class=\"footer\">\n" \
" <p>\n" \ " <p>\n" \
" <acronym title=\"Copyright\">&copy;</acronym> 2018 The Qt Company Ltd.\n" \ " <acronym title=\"Copyright\">&copy;</acronym> 2019 The Qt Company Ltd.\n" \
" Documentation contributions included herein are the copyrights of\n" \ " Documentation contributions included herein are the copyrights of\n" \
" their respective owners.<br/>" \ " their respective owners.<br/>" \
" The documentation provided herein is licensed under the terms of the" \ " The documentation provided herein is licensed under the terms of the" \

View File

@ -5,7 +5,7 @@
HTML.footer = \ HTML.footer = \
" </div>\n" \ " </div>\n" \
" <p class=\"copy-notice\">\n" \ " <p class=\"copy-notice\">\n" \
" <acronym title=\"Copyright\">&copy;</acronym> 2018 The Qt Company Ltd.\n" \ " <acronym title=\"Copyright\">&copy;</acronym> 2019 The Qt Company Ltd.\n" \
" Documentation contributions included herein are the copyrights of\n" \ " Documentation contributions included herein are the copyrights of\n" \
" their respective owners. " \ " their respective owners. " \
" The documentation provided herein is licensed under the terms of the" \ " The documentation provided herein is licensed under the terms of the" \

View File

@ -181,6 +181,13 @@ void RenderWindow::setupVertexAttribs()
m_vbo.release(); m_vbo.release();
} }
bool RenderWindow::event(QEvent *ev)
{
if (ev->type() == QEvent::UpdateRequest)
render();
return QWindow::event(ev);
}
void RenderWindow::render() void RenderWindow::render()
{ {
if (!m_context->makeCurrent(this)) { if (!m_context->makeCurrent(this)) {
@ -227,9 +234,5 @@ void RenderWindow::render()
m_angle += 1.0f; m_angle += 1.0f;
// Instead of 0 wait a few more milliseconds before rendering again. This is requestUpdate();
// only here to make the UI widgets more responsive on slower machines. We
// can afford it since our rendering is so lightweight.
const int interval = 5;
QTimer::singleShot(interval, this, &RenderWindow::render);
} }

View File

@ -72,6 +72,9 @@ signals:
void ready(); void ready();
void error(const QString &msg); void error(const QString &msg);
protected:
bool event(QEvent *ev) override;
private slots: private slots:
void render(); void render();

View File

@ -98,6 +98,15 @@ void HelloWindow::exposeEvent(QExposeEvent *)
m_renderer->render(); m_renderer->render();
} }
bool HelloWindow::event(QEvent *ev)
{
if (ev->type() == QEvent::UpdateRequest) {
m_renderer->render();
requestUpdate();
}
return QWindow::event(ev);
}
void HelloWindow::mousePressEvent(QMouseEvent *) void HelloWindow::mousePressEvent(QMouseEvent *)
{ {
updateColor(); updateColor();
@ -132,7 +141,7 @@ void Renderer::setAnimating(HelloWindow *window, bool animating)
if (animating) { if (animating) {
m_windows << window; m_windows << window;
if (m_windows.size() == 1) if (m_windows.size() == 1)
QTimer::singleShot(0, this, &Renderer::render); window->requestUpdate();
} else { } else {
m_currentWindow = 0; m_currentWindow = 0;
m_windows.removeOne(window); m_windows.removeOne(window);
@ -196,8 +205,6 @@ void Renderer::render()
m_context->swapBuffers(surface); m_context->swapBuffers(surface);
m_fAngle += 1.0f; m_fAngle += 1.0f;
QTimer::singleShot(0, this, &Renderer::render);
} }
Q_GLOBAL_STATIC(QMutex, initMutex) Q_GLOBAL_STATIC(QMutex, initMutex)

View File

@ -112,11 +112,12 @@ public:
QColor color() const; QColor color() const;
void updateColor(); void updateColor();
protected:
bool event(QEvent *ev) override;
void exposeEvent(QExposeEvent *event) override; void exposeEvent(QExposeEvent *event) override;
private:
void mousePressEvent(QMouseEvent *) override; void mousePressEvent(QMouseEvent *) override;
private:
int m_colorIndex; int m_colorIndex;
QColor m_color; QColor m_color;
const QSharedPointer<Renderer> m_renderer; const QSharedPointer<Renderer> m_renderer;

View File

@ -14,6 +14,7 @@ include(unix.conf)
QMAKE_RESOURCE = /Developer/Tools/Rez QMAKE_RESOURCE = /Developer/Tools/Rez
QMAKE_EXTENSION_SHLIB = dylib QMAKE_EXTENSION_SHLIB = dylib
QMAKE_EXTENSIONS_AUX_SHLIB = tbd
QMAKE_LIBDIR = QMAKE_LIBDIR =
# sdk.prf will prefix the proper SDK sysroot # sdk.prf will prefix the proper SDK sysroot

View File

@ -531,8 +531,11 @@ defineTest(qtConfResolveLibs) {
unix { unix {
# Under UNIX, we look for actual shared libraries, in addition # Under UNIX, we look for actual shared libraries, in addition
# to static ones. # to static ones.
shexts = $$QMAKE_EXTENSION_SHLIB $$QMAKE_EXTENSIONS_AUX_SHLIB
for (ext, shexts) {
lcan += $${QMAKE_PREFIX_SHLIB}$${lib}.$${ext}
}
lcan += \ lcan += \
$${QMAKE_PREFIX_SHLIB}$${lib}.$${QMAKE_EXTENSION_SHLIB} \
$${QMAKE_PREFIX_STATICLIB}$${lib}.$${QMAKE_EXTENSION_STATICLIB} $${QMAKE_PREFIX_STATICLIB}$${lib}.$${QMAKE_EXTENSION_STATICLIB}
} else { } else {
# Under Windows, we look only for static libraries, as even for DLLs # Under Windows, we look only for static libraries, as even for DLLs

View File

@ -1,4 +1,4 @@
QMAKE_TARGET_COMPANY = The Qt Company Ltd. QMAKE_TARGET_COMPANY = The Qt Company Ltd.
isEmpty(QMAKE_TARGET_PRODUCT): QMAKE_TARGET_PRODUCT = Qt5 isEmpty(QMAKE_TARGET_PRODUCT): QMAKE_TARGET_PRODUCT = Qt5
isEmpty(QMAKE_TARGET_DESCRIPTION): QMAKE_TARGET_DESCRIPTION = C++ Application Development Framework isEmpty(QMAKE_TARGET_DESCRIPTION): QMAKE_TARGET_DESCRIPTION = C++ Application Development Framework
QMAKE_TARGET_COPYRIGHT = Copyright (C) 2018 The Qt Company Ltd. QMAKE_TARGET_COPYRIGHT = Copyright (C) 2019 The Qt Company Ltd.

View File

@ -10,7 +10,6 @@ build_pass {
windeployqt.commands = $$QMAKE_WINDEPLOYQT $$WINDEPLOYQT_OPTIONS -list target $$WINDEPLOYQT_TARGET > $$WINDEPLOYQT_OUTPUT windeployqt.commands = $$QMAKE_WINDEPLOYQT $$WINDEPLOYQT_OPTIONS -list target $$WINDEPLOYQT_TARGET > $$WINDEPLOYQT_OUTPUT
windeployqt_clean.commands = if exist $$WINDEPLOYQT_OUTPUT for /f %i in ($$WINDEPLOYQT_OUTPUT) do $$QMAKE_DEL_FILE %~fi && $$QMAKE_DEL_DIR %~pi windeployqt_clean.commands = if exist $$WINDEPLOYQT_OUTPUT for /f %i in ($$WINDEPLOYQT_OUTPUT) do $$QMAKE_DEL_FILE %~fi && $$QMAKE_DEL_DIR %~pi
QMAKE_EXTRA_TARGETS += windeployqt_clean
DISTCLEAN_DEPS += windeployqt_clean DISTCLEAN_DEPS += windeployqt_clean
QMAKE_DISTCLEAN += $$WINDEPLOYQT_OUTPUT QMAKE_DISTCLEAN += $$WINDEPLOYQT_OUTPUT
} else { } else {

View File

@ -20,7 +20,6 @@ EMCC_COMMON_LFLAGS = \
-s NO_EXIT_RUNTIME=0 \ -s NO_EXIT_RUNTIME=0 \
-s ERROR_ON_UNDEFINED_SYMBOLS=1 \ -s ERROR_ON_UNDEFINED_SYMBOLS=1 \
--bind \ --bind \
-s \"BINARYEN_METHOD=\'native-wasm\'\" \
-s \"BINARYEN_TRAP_MODE=\'clamp\'\" -s \"BINARYEN_TRAP_MODE=\'clamp\'\"
# The -s arguments can also be used with release builds, # The -s arguments can also be used with release builds,

View File

@ -0,0 +1,19 @@
#
# qmake configuration for winrt-arm64-msvc2017
#
# Written for Microsoft Visual C++ 2017
#
include(../common/winrt_winphone/qmake.conf)
DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_PC_APP WINAPI_PARTITION_PHONE_APP=1 arm64 __arm64__ __arm64__
QMAKE_CFLAGS += -FS
QMAKE_CXXFLAGS += -FS
QMAKE_LFLAGS += /MACHINE:arm64 /NODEFAULTLIB:kernel32.lib
QMAKE_LIBS += windowscodecs.lib WindowsApp.lib runtimeobject.lib OneCore.lib
VCPROJ_ARCH = arm64
WINSDK_VER = 10.0
WINRT_MANIFEST = $$PWD/../common/winrt_winphone/manifests/10.0/AppxManifest.xml.in
WINRT_MANIFEST.architecture = arm64

View File

@ -0,0 +1,40 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the qmake spec of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "../common/winrt_winphone/qplatformdefs.h"

View File

@ -424,6 +424,9 @@ MakefileGenerator::init()
} }
incs.append(project->specDir()); incs.append(project->specDir());
const auto platform = v["QMAKE_PLATFORM"];
resolveDependenciesInFrameworks = platform.contains("darwin");
const char * const cacheKeys[] = { "_QMAKE_STASH_", "_QMAKE_SUPER_CACHE_", nullptr }; const char * const cacheKeys[] = { "_QMAKE_STASH_", "_QMAKE_SUPER_CACHE_", nullptr };
for (int i = 0; cacheKeys[i]; ++i) { for (int i = 0; cacheKeys[i]; ++i) {
if (v[cacheKeys[i]].isEmpty()) if (v[cacheKeys[i]].isEmpty())
@ -1839,6 +1842,33 @@ static QStringList splitDeps(const QString &indeps, bool lineMode)
return deps; return deps;
} }
QString MakefileGenerator::resolveDependency(const QDir &outDir, const QString &file)
{
const QList<QMakeLocalFileName> &depdirs = QMakeSourceFileInfo::dependencyPaths();
for (const auto &depdir : depdirs) {
const QString &local = depdir.local();
QString lf = outDir.absoluteFilePath(local + '/' + file);
if (exists(lf))
return lf;
if (resolveDependenciesInFrameworks) {
// Given a file like "QtWidgets/QWidget", try to resolve it
// as framework header "QtWidgets.framework/Headers/QWidget".
int cut = file.indexOf('/');
if (cut < 0 || cut + 1 >= file.size())
continue;
QStringRef framework = file.leftRef(cut);
QStringRef include = file.midRef(cut + 1);
if (local.endsWith('/' + framework + ".framework/Headers")) {
lf = outDir.absoluteFilePath(local + '/' + include);
if (exists(lf))
return lf;
}
}
}
return {};
}
void void
MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
{ {
@ -1991,16 +2021,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
} else if (exists(absFile)) { } else if (exists(absFile)) {
file = absFile; file = absFile;
} else { } else {
QString localFile; QString localFile = resolveDependency(outDir, file);
QList<QMakeLocalFileName> depdirs = QMakeSourceFileInfo::dependencyPaths();
for (QList<QMakeLocalFileName>::Iterator dit = depdirs.begin();
dit != depdirs.end(); ++dit) {
QString lf = outDir.absoluteFilePath((*dit).local() + '/' + file);
if (exists(lf)) {
localFile = lf;
break;
}
}
if (localFile.isEmpty()) { if (localFile.isEmpty()) {
if (exists(file)) if (exists(file))
warn_msg(WarnDeprecated, ".depend_command for extra compiler %s" warn_msg(WarnDeprecated, ".depend_command for extra compiler %s"
@ -2088,16 +2109,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
} else if (exists(absFile)) { } else if (exists(absFile)) {
file = absFile; file = absFile;
} else { } else {
QString localFile; QString localFile = resolveDependency(outDir, file);
QList<QMakeLocalFileName> depdirs = QMakeSourceFileInfo::dependencyPaths();
for (QList<QMakeLocalFileName>::Iterator dit = depdirs.begin();
dit != depdirs.end(); ++dit) {
QString lf = outDir.absoluteFilePath((*dit).local() + '/' + file);
if (exists(lf)) {
localFile = lf;
break;
}
}
if (localFile.isEmpty()) { if (localFile.isEmpty()) {
if (exists(file)) if (exists(file))
warn_msg(WarnDeprecated, ".depend_command for extra compiler %s" warn_msg(WarnDeprecated, ".depend_command for extra compiler %s"

View File

@ -55,6 +55,7 @@ class MakefileGenerator : protected QMakeSourceFileInfo
{ {
QString spec; QString spec;
bool no_io; bool no_io;
bool resolveDependenciesInFrameworks = false;
QHash<QString, bool> init_compiler_already; QHash<QString, bool> init_compiler_already;
QString makedir, chkexists; QString makedir, chkexists;
QString build_args(); QString build_args();
@ -82,6 +83,7 @@ protected:
void writeExportedVariables(QTextStream &t); void writeExportedVariables(QTextStream &t);
void writeExtraVariables(QTextStream &t); void writeExtraVariables(QTextStream &t);
void writeExtraTargets(QTextStream &t); void writeExtraTargets(QTextStream &t);
QString resolveDependency(const QDir &outDir, const QString &file);
void writeExtraCompilerTargets(QTextStream &t); void writeExtraCompilerTargets(QTextStream &t);
void writeExtraCompilerVariables(QTextStream &t); void writeExtraCompilerVariables(QTextStream &t);
bool writeDummyMakefile(QTextStream &t); bool writeDummyMakefile(QTextStream &t);

View File

@ -84,6 +84,8 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
if (impexts.isEmpty()) if (impexts.isEmpty())
impexts = project->values("QMAKE_EXTENSION_STATICLIB"); impexts = project->values("QMAKE_EXTENSION_STATICLIB");
QList<QMakeLocalFileName> dirs; QList<QMakeLocalFileName> dirs;
for (const ProString &dlib : project->values("QMAKE_DEFAULT_LIBDIRS"))
dirs.append(QMakeLocalFileName(dlib.toQString()));
static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE", static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE",
"QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr }; "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
for (int i = 0; lflags[i]; i++) { for (int i = 0; lflags[i]; i++) {

View File

@ -7,7 +7,7 @@
"Description": "strtoll() and strtoull() are functions for converting a string to (unsigned) long long integer.", "Description": "strtoll() and strtoull() are functions for converting a string to (unsigned) long long integer.",
"Homepage": "https://github.com/freebsd/freebsd/", "Homepage": "https://github.com/freebsd/freebsd/",
"Upstream": "https://raw.githubusercontent.com/freebsd/freebsd/raw/tree/master/lib/libc/stdlib/$file", "DownloadLocation": "https://github.com/freebsd/freebsd/tree/master/lib/libc/stdlib",
"Version": "upstream has complicated with std locales; do not update", "Version": "upstream has complicated with std locales; do not update",
"Version": "18b29f3fb8abee5d57ed8f4a44f806bec7e0eeff", "Version": "18b29f3fb8abee5d57ed8f4a44f806bec7e0eeff",
"License": "BSD 3-clause \"New\" or \"Revised\" License", "License": "BSD 3-clause \"New\" or \"Revised\" License",

View File

@ -69,8 +69,11 @@ DEFINES += FT2_BUILD_LIBRARY
DEFINES += FT_CONFIG_OPTION_SYSTEM_ZLIB DEFINES += FT_CONFIG_OPTION_SYSTEM_ZLIB
include(../zlib_dependency.pri) include(../zlib_dependency.pri)
DEFINES += FT_CONFIG_OPTION_USE_PNG
include($$OUT_PWD/../../gui/qtgui-config.pri) include($$OUT_PWD/../../gui/qtgui-config.pri)
QMAKE_USE_PRIVATE += libpng QT_FOR_CONFIG += gui-private
qtConfig(png) {
DEFINES += FT_CONFIG_OPTION_USE_PNG
QMAKE_USE_PRIVATE += libpng
}
DEFINES += TT_CONFIG_OPTION_SUBPIXEL_HINTING DEFINES += TT_CONFIG_OPTION_SUBPIXEL_HINTING

View File

@ -6,8 +6,8 @@
"Description": "SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine.", "Description": "SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine.",
"Homepage": "https://www.sqlite.org/", "Homepage": "https://www.sqlite.org/",
"Version": "3.24.0", "Version": "3.26.0",
"DownloadLocation": "https://www.sqlite.org/2018/sqlite-amalgamation-3240000.zip", "DownloadLocation": "https://www.sqlite.org/2018/sqlite-amalgamation-3260000.zip",
"License": "Public Domain", "License": "Public Domain",
"Copyright": "The authors disclaim copyright to the source code. However, a license can be obtained if needed." "Copyright": "The authors disclaim copyright to the source code. However, a license can be obtained if needed."
} }

File diff suppressed because it is too large Load Diff

View File

@ -123,9 +123,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()]. ** [sqlite_version()] and [sqlite_source_id()].
*/ */
#define SQLITE_VERSION "3.25.2" #define SQLITE_VERSION "3.26.0"
#define SQLITE_VERSION_NUMBER 3025002 #define SQLITE_VERSION_NUMBER 3026000
#define SQLITE_SOURCE_ID "2018-09-25 19:08:10 fb90e7189ae6d62e77ba3a308ca5d683f90bbe633cf681865365b8e92792d1c7" #define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9"
/* /*
** CAPI3REF: Run-Time Library Version Numbers ** CAPI3REF: Run-Time Library Version Numbers
@ -2017,6 +2017,7 @@ struct sqlite3_mem_methods {
** is invoked. ** is invoked.
** **
** <dl> ** <dl>
** [[SQLITE_DBCONFIG_LOOKASIDE]]
** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt> ** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
** <dd> ^This option takes three additional arguments that determine the ** <dd> ^This option takes three additional arguments that determine the
** [lookaside memory allocator] configuration for the [database connection]. ** [lookaside memory allocator] configuration for the [database connection].
@ -2039,6 +2040,7 @@ struct sqlite3_mem_methods {
** memory is in use leaves the configuration unchanged and returns ** memory is in use leaves the configuration unchanged and returns
** [SQLITE_BUSY].)^</dd> ** [SQLITE_BUSY].)^</dd>
** **
** [[SQLITE_DBCONFIG_ENABLE_FKEY]]
** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt> ** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt>
** <dd> ^This option is used to enable or disable the enforcement of ** <dd> ^This option is used to enable or disable the enforcement of
** [foreign key constraints]. There should be two additional arguments. ** [foreign key constraints]. There should be two additional arguments.
@ -2049,6 +2051,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in ** following this call. The second parameter may be a NULL pointer, in
** which case the FK enforcement setting is not reported back. </dd> ** which case the FK enforcement setting is not reported back. </dd>
** **
** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]]
** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt> ** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt>
** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers]. ** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers].
** There should be two additional arguments. ** There should be two additional arguments.
@ -2059,6 +2062,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in ** following this call. The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd> ** which case the trigger setting is not reported back. </dd>
** **
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the two-argument ** <dd> ^This option is used to enable or disable the two-argument
** version of the [fts3_tokenizer()] function which is part of the ** version of the [fts3_tokenizer()] function which is part of the
@ -2072,6 +2076,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in ** following this call. The second parameter may be a NULL pointer, in
** which case the new setting is not reported back. </dd> ** which case the new setting is not reported back. </dd>
** **
** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]]
** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt>
** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()] ** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()]
** interface independently of the [load_extension()] SQL function. ** interface independently of the [load_extension()] SQL function.
@ -2089,7 +2094,7 @@ struct sqlite3_mem_methods {
** be a NULL pointer, in which case the new setting is not reported back. ** be a NULL pointer, in which case the new setting is not reported back.
** </dd> ** </dd>
** **
** <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> ** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt>
** <dd> ^This option is used to change the name of the "main" database ** <dd> ^This option is used to change the name of the "main" database
** schema. ^The sole argument is a pointer to a constant UTF8 string ** schema. ^The sole argument is a pointer to a constant UTF8 string
** which will become the new schema name in place of "main". ^SQLite ** which will become the new schema name in place of "main". ^SQLite
@ -2098,6 +2103,7 @@ struct sqlite3_mem_methods {
** until after the database connection closes. ** until after the database connection closes.
** </dd> ** </dd>
** **
** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]]
** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
** <dd> Usually, when a database in wal mode is closed or detached from a ** <dd> Usually, when a database in wal mode is closed or detached from a
** database handle, SQLite checks if this will mean that there are now no ** database handle, SQLite checks if this will mean that there are now no
@ -2111,7 +2117,7 @@ struct sqlite3_mem_methods {
** have been disabled - 0 if they are not disabled, 1 if they are. ** have been disabled - 0 if they are not disabled, 1 if they are.
** </dd> ** </dd>
** **
** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> ** [[SQLITE_DBCONFIG_ENABLE_QPSG]] <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates ** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates
** the [query planner stability guarantee] (QPSG). When the QPSG is active, ** the [query planner stability guarantee] (QPSG). When the QPSG is active,
** a single SQL query statement will always use the same algorithm regardless ** a single SQL query statement will always use the same algorithm regardless
@ -2127,7 +2133,7 @@ struct sqlite3_mem_methods {
** following this call. ** following this call.
** </dd> ** </dd>
** **
** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> ** [[SQLITE_DBCONFIG_TRIGGER_EQP]] <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt>
** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not ** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not
** include output for any operations performed by trigger programs. This ** include output for any operations performed by trigger programs. This
** option is used to set or clear (the default) a flag that governs this ** option is used to set or clear (the default) a flag that governs this
@ -2139,7 +2145,7 @@ struct sqlite3_mem_methods {
** it is not disabled, 1 if it is. ** it is not disabled, 1 if it is.
** </dd> ** </dd>
** **
** <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt> ** [[SQLITE_DBCONFIG_RESET_DATABASE]] <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt>
** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run ** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run
** [VACUUM] in order to reset a database back to an empty database ** [VACUUM] in order to reset a database back to an empty database
** with no schema and no content. The following process works even for ** with no schema and no content. The following process works even for
@ -2158,6 +2164,18 @@ struct sqlite3_mem_methods {
** Because resetting a database is destructive and irreversible, the ** Because resetting a database is destructive and irreversible, the
** process requires the use of this obscure API and multiple steps to help ** process requires the use of this obscure API and multiple steps to help
** ensure that it does not happen by accident. ** ensure that it does not happen by accident.
**
** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt>
** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the
** "defensive" flag for a database connection. When the defensive
** flag is enabled, language features that allow ordinary SQL to
** deliberately corrupt the database file are disabled. The disabled
** features include but are not limited to the following:
** <ul>
** <li> The [PRAGMA writable_schema=ON] statement.
** <li> Writes to the [sqlite_dbpage] virtual table.
** <li> Direct writes to [shadow tables].
** </ul>
** </dd> ** </dd>
** </dl> ** </dl>
*/ */
@ -2171,7 +2189,8 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */ #define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ #define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */
#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */ #define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */
#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */
/* /*
** CAPI3REF: Enable Or Disable Extended Result Codes ** CAPI3REF: Enable Or Disable Extended Result Codes
@ -3609,9 +3628,19 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** on this hint by avoiding the use of [lookaside memory] so as not to ** on this hint by avoiding the use of [lookaside memory] so as not to
** deplete the limited store of lookaside memory. Future versions of ** deplete the limited store of lookaside memory. Future versions of
** SQLite may act on this hint differently. ** SQLite may act on this hint differently.
**
** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt>
** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized
** representation of the SQL statement should be calculated and then
** associated with the prepared statement, which can be obtained via
** the [sqlite3_normalized_sql()] interface.)^ The semantics used to
** normalize a SQL statement are unspecified and subject to change.
** At a minimum, literal values will be replaced with suitable
** placeholders.
** </dl> ** </dl>
*/ */
#define SQLITE_PREPARE_PERSISTENT 0x01 #define SQLITE_PREPARE_PERSISTENT 0x01
#define SQLITE_PREPARE_NORMALIZE 0x02
/* /*
** CAPI3REF: Compiling An SQL Statement ** CAPI3REF: Compiling An SQL Statement
@ -3769,6 +3798,11 @@ SQLITE_API int sqlite3_prepare16_v3(
** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8 ** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8
** string containing the SQL text of prepared statement P with ** string containing the SQL text of prepared statement P with
** [bound parameters] expanded. ** [bound parameters] expanded.
** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8
** string containing the normalized SQL text of prepared statement P. The
** semantics used to normalize a SQL statement are unspecified and subject
** to change. At a minimum, literal values will be replaced with suitable
** placeholders.
** **
** ^(For example, if a prepared statement is created using the SQL ** ^(For example, if a prepared statement is created using the SQL
** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 ** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345
@ -3784,14 +3818,16 @@ SQLITE_API int sqlite3_prepare16_v3(
** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time
** option causes sqlite3_expanded_sql() to always return NULL. ** option causes sqlite3_expanded_sql() to always return NULL.
** **
** ^The string returned by sqlite3_sql(P) is managed by SQLite and is ** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P)
** automatically freed when the prepared statement is finalized. ** are managed by SQLite and are automatically freed when the prepared
** statement is finalized.
** ^The string returned by sqlite3_expanded_sql(P), on the other hand, ** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
** is obtained from [sqlite3_malloc()] and must be free by the application ** is obtained from [sqlite3_malloc()] and must be free by the application
** by passing it to [sqlite3_free()]. ** by passing it to [sqlite3_free()].
*/ */
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
/* /*
** CAPI3REF: Determine If An SQL Statement Writes The Database ** CAPI3REF: Determine If An SQL Statement Writes The Database
@ -6281,6 +6317,9 @@ struct sqlite3_module {
int (*xSavepoint)(sqlite3_vtab *pVTab, int); int (*xSavepoint)(sqlite3_vtab *pVTab, int);
int (*xRelease)(sqlite3_vtab *pVTab, int); int (*xRelease)(sqlite3_vtab *pVTab, int);
int (*xRollbackTo)(sqlite3_vtab *pVTab, int); int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
/* The methods above are in versions 1 and 2 of the sqlite_module object.
** Those below are for version 3 and greater. */
int (*xShadowName)(const char*);
}; };
/* /*
@ -7203,6 +7242,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
@ -8615,6 +8655,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
** can use to customize and optimize their behavior. ** can use to customize and optimize their behavior.
** **
** <dl> ** <dl>
** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]]
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT ** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
** <dd>Calls of the form ** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
@ -9384,7 +9425,7 @@ struct sqlite3_rtree_query_info {
sqlite3_int64 iRowid; /* Rowid for current entry */ sqlite3_int64 iRowid; /* Rowid for current entry */
sqlite3_rtree_dbl rParentScore; /* Score of parent node */ sqlite3_rtree_dbl rParentScore; /* Score of parent node */
int eParentWithin; /* Visibility of parent node */ int eParentWithin; /* Visibility of parent node */
int eWithin; /* OUT: Visiblity */ int eWithin; /* OUT: Visibility */
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
/* The following fields are only available in 3.8.11 and later */ /* The following fields are only available in 3.8.11 and later */
sqlite3_value **apSqlParam; /* Original SQL values of parameters */ sqlite3_value **apSqlParam; /* Original SQL values of parameters */
@ -9880,12 +9921,38 @@ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
** consecutively. There is no chance that the iterator will visit a change ** consecutively. There is no chance that the iterator will visit a change
** the applies to table X, then one for table Y, and then later on visit ** the applies to table X, then one for table Y, and then later on visit
** another change for table X. ** another change for table X.
**
** The behavior of sqlite3changeset_start_v2() and its streaming equivalent
** may be modified by passing a combination of
** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter.
**
** Note that the sqlite3changeset_start_v2() API is still <b>experimental</b>
** and therefore subject to change.
*/ */
SQLITE_API int sqlite3changeset_start( SQLITE_API int sqlite3changeset_start(
sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
int nChangeset, /* Size of changeset blob in bytes */ int nChangeset, /* Size of changeset blob in bytes */
void *pChangeset /* Pointer to blob containing changeset */ void *pChangeset /* Pointer to blob containing changeset */
); );
SQLITE_API int sqlite3changeset_start_v2(
sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
int nChangeset, /* Size of changeset blob in bytes */
void *pChangeset, /* Pointer to blob containing changeset */
int flags /* SESSION_CHANGESETSTART_* flags */
);
/*
** CAPI3REF: Flags for sqlite3changeset_start_v2
**
** The following flags may passed via the 4th parameter to
** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
**
** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
** Invert the changeset while iterating through it. This is equivalent to
** inverting a changeset using sqlite3changeset_invert() before applying it.
** It is an error to specify this flag with a patchset.
*/
#define SQLITE_CHANGESETSTART_INVERT 0x0002
/* /*
@ -10540,7 +10607,7 @@ SQLITE_API int sqlite3changeset_apply_v2(
), ),
void *pCtx, /* First argument passed to xConflict */ void *pCtx, /* First argument passed to xConflict */
void **ppRebase, int *pnRebase, /* OUT: Rebase data */ void **ppRebase, int *pnRebase, /* OUT: Rebase data */
int flags /* Combination of SESSION_APPLY_* flags */ int flags /* SESSION_CHANGESETAPPLY_* flags */
); );
/* /*
@ -10558,8 +10625,14 @@ SQLITE_API int sqlite3changeset_apply_v2(
** causes the sessions module to omit this savepoint. In this case, if the ** causes the sessions module to omit this savepoint. In this case, if the
** caller has an open transaction or savepoint when apply_v2() is called, ** caller has an open transaction or savepoint when apply_v2() is called,
** it may revert the partially applied changeset by rolling it back. ** it may revert the partially applied changeset by rolling it back.
**
** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
** Invert the changeset before applying it. This is equivalent to inverting
** a changeset using sqlite3changeset_invert() before applying it. It is
** an error to specify this flag with a patchset.
*/ */
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
/* /*
** CAPI3REF: Constants Passed To The Conflict Handler ** CAPI3REF: Constants Passed To The Conflict Handler
@ -10953,6 +11026,12 @@ SQLITE_API int sqlite3changeset_start_strm(
int (*xInput)(void *pIn, void *pData, int *pnData), int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn void *pIn
); );
SQLITE_API int sqlite3changeset_start_v2_strm(
sqlite3_changeset_iter **pp,
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn,
int flags
);
SQLITE_API int sqlite3session_changeset_strm( SQLITE_API int sqlite3session_changeset_strm(
sqlite3_session *pSession, sqlite3_session *pSession,
int (*xOutput)(void *pOut, const void *pData, int nData), int (*xOutput)(void *pOut, const void *pData, int nData),
@ -10979,6 +11058,45 @@ SQLITE_API int sqlite3rebaser_rebase_strm(
void *pOut void *pOut
); );
/*
** CAPI3REF: Configure global parameters
**
** The sqlite3session_config() interface is used to make global configuration
** changes to the sessions module in order to tune it to the specific needs
** of the application.
**
** The sqlite3session_config() interface is not threadsafe. If it is invoked
** while any other thread is inside any other sessions method then the
** results are undefined. Furthermore, if it is invoked after any sessions
** related objects have been created, the results are also undefined.
**
** The first argument to the sqlite3session_config() function must be one
** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The
** interpretation of the (void*) value passed as the second parameter and
** the effect of calling this function depends on the value of the first
** parameter.
**
** <dl>
** <dt>SQLITE_SESSION_CONFIG_STRMSIZE<dd>
** By default, the sessions module streaming interfaces attempt to input
** and output data in approximately 1 KiB chunks. This operand may be used
** to set and query the value of this configuration setting. The pointer
** passed as the second argument must point to a value of type (int).
** If this value is greater than 0, it is used as the new streaming data
** chunk size for both input and output. Before returning, the (int) value
** pointed to by pArg is set to the final value of the streaming interface
** chunk size.
** </dl>
**
** This function returns SQLITE_OK if successful, or an SQLite error code
** otherwise.
*/
SQLITE_API int sqlite3session_config(int op, void *pArg);
/*
** CAPI3REF: Values for sqlite3session_config().
*/
#define SQLITE_SESSION_CONFIG_STRMSIZE 1
/* /*
** Make sure we can call this stuff from C++. ** Make sure we can call this stuff from C++.

View File

@ -612,7 +612,7 @@ public abstract class QtLoader {
} }
if (m_qtLibs != null) { if (m_qtLibs != null) {
String libPrefix = apkDeployFromSystem ? libsDir + "lib" : localPrefix + "lib/lib"; String libPrefix = libsDir + "lib";
for (int i = 0; i < m_qtLibs.length; i++) for (int i = 0; i < m_qtLibs.length; i++)
libraryList.add(libPrefix + m_qtLibs[i] + ".so"); libraryList.add(libPrefix + m_qtLibs[i] + ".so");
} }

View File

@ -1,5 +1,17 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<manifest package="org.qtproject.example" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto"> <manifest package="org.qtproject.example" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
Remove the comment if you do not require these default permissions. -->
<!-- %%INSERT_PERMISSIONS -->
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
Remove the comment if you do not require these default features. -->
<!-- %%INSERT_FEATURES -->
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --"> <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
android:name="org.qtproject.qt5.android.bindings.QtActivity" android:name="org.qtproject.qt5.android.bindings.QtActivity"
@ -70,15 +82,4 @@
</application> </application>
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
Remove the comment if you do not require these default permissions. -->
<!-- %%INSERT_PERMISSIONS -->
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
Remove the comment if you do not require these default features. -->
<!-- %%INSERT_FEATURES -->
</manifest> </manifest>

View File

@ -83,8 +83,12 @@ QString QWindowsLocalCodec::convertToUnicode(const char *chars, int length, Conv
len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
prev, 2, wc.data(), wc.length()); prev, 2, wc.data(), wc.length());
if (len) { if (len) {
prepend = true;
sp.append(QChar(wc[0])); sp.append(QChar(wc[0]));
if (mblen == 1) {
state->remainingChars = 0;
return sp;
}
prepend = true;
mb++; mb++;
mblen--; mblen--;
wc[0] = 0; wc[0] = 0;

View File

@ -45,6 +45,9 @@ excludedirs += snippets
excludefiles += ../../../examples/widgets/tools/customcompleter/doc/src/customcompleter.qdoc \ excludefiles += ../../../examples/widgets/tools/customcompleter/doc/src/customcompleter.qdoc \
../../../examples/widgets/tools/codecs/doc/src/codecs.qdoc ../../../examples/widgets/tools/codecs/doc/src/codecs.qdoc
# Included in qttestlib.qdocconf instead
excludefiles += ../kernel/qtestsupport_core.cpp
manifestmeta.highlighted.names = "QtCore/JSON Save Game Example" \ manifestmeta.highlighted.names = "QtCore/JSON Save Game Example" \
"QtCore/Local Fortune*" "QtCore/Local Fortune*"

View File

@ -2050,6 +2050,8 @@ static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSyst
return "Sierra"; return "Sierra";
case 13: case 13:
return "High Sierra"; return "High Sierra";
case 14:
return "Mojave";
} }
} }
// unknown, future version // unknown, future version

View File

@ -348,7 +348,7 @@ template <> inline bool mul_overflow(qint64 v1, qint64 v2, qint64 *r)
// as signed for the low bits and use a signed right shift to verify that // as signed for the low bits and use a signed right shift to verify that
// 'high' is nothing but sign bits that match the sign of 'low'. // 'high' is nothing but sign bits that match the sign of 'low'.
qint64 high = __mulh(v1, v2); qint64 high = Q_SMULH(v1, v2);
*r = qint64(quint64(v1) * quint64(v2)); *r = qint64(quint64(v1) * quint64(v2));
return (*r >> 63) != high; return (*r >> 63) != high;
} }

View File

@ -748,6 +748,21 @@ static int drivePrefixLength(const QString &path)
} }
#endif // Q_OS_WIN #endif // Q_OS_WIN
static bool treatAsAbsolute(const QString &path)
{
// ### Qt 6: be consistent about absolute paths
// QFileInfo will use the right FS-engine for virtual file-systems
// (e.g. resource paths). Unfortunately, for real file-systems, it relies
// on QFileSystemEntry's isRelative(), which is flawed on MS-Win, ignoring
// its (correct) isAbsolute(). So only use that isAbsolute() unless there's
// a colon in the path.
// FIXME: relies on virtual file-systems having colons in their prefixes.
// The case of an MS-absolute C:/... path happens to work either way.
return (path.contains(QLatin1Char(':')) && QFileInfo(path).isAbsolute())
|| QFileSystemEntry(path).isAbsolute();
}
/*! /*!
Returns the path name of a file in the directory. Does \e not Returns the path name of a file in the directory. Does \e not
check if the file actually exists in the directory; but see check if the file actually exists in the directory; but see
@ -759,13 +774,10 @@ static int drivePrefixLength(const QString &path)
*/ */
QString QDir::filePath(const QString &fileName) const QString QDir::filePath(const QString &fileName) const
{ {
const QDirPrivate* d = d_ptr.constData(); if (treatAsAbsolute(fileName))
// Mistrust our own isAbsolutePath() for real files; Q_OS_WIN needs a drive.
if (fileName.startsWith(QLatin1Char(':')) // i.e. resource path
? isAbsolutePath(fileName) : QFileSystemEntry(fileName).isAbsolute()) {
return fileName; return fileName;
}
const QDirPrivate* d = d_ptr.constData();
QString ret = d->dirEntry.filePath(); QString ret = d->dirEntry.filePath();
if (fileName.isEmpty()) if (fileName.isEmpty())
return ret; return ret;
@ -793,13 +805,10 @@ QString QDir::filePath(const QString &fileName) const
*/ */
QString QDir::absoluteFilePath(const QString &fileName) const QString QDir::absoluteFilePath(const QString &fileName) const
{ {
const QDirPrivate* d = d_ptr.constData(); if (treatAsAbsolute(fileName))
// Mistrust our own isAbsolutePath() for real files; Q_OS_WIN needs a drive.
if (fileName.startsWith(QLatin1Char(':')) // i.e. resource path
? isAbsolutePath(fileName) : QFileSystemEntry(fileName).isAbsolute()) {
return fileName; return fileName;
}
const QDirPrivate* d = d_ptr.constData();
d->resolveAbsoluteEntry(); d->resolveAbsoluteEntry();
const QString absoluteDirPath = d->absoluteDirEntry.filePath(); const QString absoluteDirPath = d->absoluteDirEntry.filePath();
if (fileName.isEmpty()) if (fileName.isEmpty())
@ -2164,9 +2173,10 @@ bool QDir::match(const QString &filter, const QString &fileName)
This method is shared with QUrl, so it doesn't deal with QDir::separator(), This method is shared with QUrl, so it doesn't deal with QDir::separator(),
nor does it remove the trailing slash, if any. nor does it remove the trailing slash, if any.
*/ */
Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, bool allowUncPaths, QString qt_normalizePathSegments(const QString &name, QDirPrivate::PathNormalizations flags, bool *ok)
bool *ok = nullptr)
{ {
const bool allowUncPaths = QDirPrivate::AllowUncPaths & flags;
const bool isRemote = QDirPrivate::RemotePath & flags;
const int len = name.length(); const int len = name.length();
if (ok) if (ok)
@ -2188,14 +2198,30 @@ Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, bool all
i -= prefixLength; i -= prefixLength;
// replicate trailing slash (i > 0 checks for emptiness of input string p) // replicate trailing slash (i > 0 checks for emptiness of input string p)
if (i > 0 && p[i] == '/') { // except for remote paths because there can be /../ or /./ ending
if (i > 0 && p[i] == '/' && !isRemote) {
out[--used] = '/'; out[--used] = '/';
--i; --i;
} }
auto isDot = [](const ushort *p, int i) {
return i > 1 && p[i - 1] == '.' && p[i - 2] == '/';
};
auto isDotDot = [](const ushort *p, int i) {
return i > 2 && p[i - 1] == '.' && p[i - 2] == '.' && p[i - 3] == '/';
};
while (i >= 0) { while (i >= 0) {
// remove trailing slashes // copy trailing slashes for remote urls
if (p[i] == '/') { if (p[i] == '/') {
if (isRemote && !up) {
if (isDot(p, i)) {
i -= 2;
continue;
}
out[--used] = p[i];
}
--i; --i;
continue; continue;
} }
@ -2207,10 +2233,17 @@ Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, bool all
} }
// detect up dir // detect up dir
if (i >= 1 && p[i] == '.' && p[i-1] == '.' if (i >= 1 && p[i] == '.' && p[i-1] == '.' && (i < 2 || p[i - 2] == '/')) {
&& (i == 1 || (i >= 2 && p[i-2] == '/'))) {
++up; ++up;
i -= 2; i -= i >= 2 ? 3 : 2;
if (isRemote) {
// moving up should consider empty path segments too (/path//../ -> /path/)
while (i > 0 && up && p[i] == '/') {
--up;
--i;
}
}
continue; continue;
} }
@ -2220,7 +2253,27 @@ Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, bool all
// skip or copy // skip or copy
while (i >= 0) { while (i >= 0) {
if (p[i] == '/') { // do not copy slashes if (p[i] == '/') {
// copy all slashes as is for remote urls if they are not part of /./ or /../
if (isRemote && !up) {
while (i > 0 && p[i] == '/' && !isDotDot(p, i)) {
if (isDot(p, i)) {
i -= 2;
continue;
}
out[--used] = p[i];
--i;
}
// in case of /./, jump over
if (isDot(p, i))
i -= 2;
break;
}
--i; --i;
break; break;
} }
@ -2241,7 +2294,7 @@ Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, bool all
*ok = prefixLength == 0 || up == 0; *ok = prefixLength == 0 || up == 0;
// add remaining '..' // add remaining '..'
while (up) { while (up && !isRemote) {
if (used != len && out[used] != '/') // is not empty and there isn't already a '/' if (used != len && out[used] != '/') // is not empty and there isn't already a '/'
out[--used] = '/'; out[--used] = '/';
out[--used] = '.'; out[--used] = '.';
@ -2287,7 +2340,7 @@ static QString qt_cleanPath(const QString &path, bool *ok)
if (dir_separator != QLatin1Char('/')) if (dir_separator != QLatin1Char('/'))
name.replace(dir_separator, QLatin1Char('/')); name.replace(dir_separator, QLatin1Char('/'));
QString ret = qt_normalizePathSegments(name, OSSupportsUncPaths, ok); QString ret = qt_normalizePathSegments(name, OSSupportsUncPaths ? QDirPrivate::AllowUncPaths : QDirPrivate::DefaultNormalization, ok);
// Strip away last slash except for root directories // Strip away last slash except for root directories
if (ret.length() > 1 && ret.endsWith(QLatin1Char('/'))) { if (ret.length() > 1 && ret.endsWith(QLatin1Char('/'))) {

View File

@ -59,6 +59,14 @@ QT_BEGIN_NAMESPACE
class QDirPrivate : public QSharedData class QDirPrivate : public QSharedData
{ {
public: public:
enum PathNormalization {
DefaultNormalization = 0x00,
AllowUncPaths = 0x01,
RemotePath = 0x02
};
Q_DECLARE_FLAGS(PathNormalizations, PathNormalization)
Q_FLAGS(PathNormalizations)
explicit QDirPrivate(const QString &path, const QStringList &nameFilters_ = QStringList(), explicit QDirPrivate(const QString &path, const QStringList &nameFilters_ = QStringList(),
QDir::SortFlags sort_ = QDir::SortFlags(QDir::Name | QDir::IgnoreCase), QDir::SortFlags sort_ = QDir::SortFlags(QDir::Name | QDir::IgnoreCase),
QDir::Filters filters_ = QDir::AllEntries); QDir::Filters filters_ = QDir::AllEntries);
@ -97,6 +105,10 @@ public:
mutable QFileSystemMetaData metaData; mutable QFileSystemMetaData metaData;
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS(QDirPrivate::PathNormalizations)
Q_AUTOTEST_EXPORT QString qt_normalizePathSegments(const QString &name, QDirPrivate::PathNormalizations flags, bool *ok = nullptr);
QT_END_NAMESPACE QT_END_NAMESPACE
#endif #endif

View File

@ -1038,8 +1038,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
if (what & QFileSystemMetaData::Permissions) if (what & QFileSystemMetaData::Permissions)
fillPermissions(fname, data, what); fillPermissions(fname, data, what);
if ((what & QFileSystemMetaData::LinkType) if (what & QFileSystemMetaData::LinkType) {
&& data.missingFlags(QFileSystemMetaData::LinkType)) {
data.knownFlagsMask |= QFileSystemMetaData::LinkType; data.knownFlagsMask |= QFileSystemMetaData::LinkType;
if (data.fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT) { if (data.fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT) {
WIN32_FIND_DATA findData; WIN32_FIND_DATA findData;

View File

@ -253,7 +253,8 @@
and contains no query or fragment, a local file path is returned. and contains no query or fragment, a local file path is returned.
\value StripTrailingSlash The trailing slash is removed from the path, if one is present. \value StripTrailingSlash The trailing slash is removed from the path, if one is present.
\value NormalizePathSegments Modifies the path to remove redundant directory separators, \value NormalizePathSegments Modifies the path to remove redundant directory separators,
and to resolve "."s and ".."s (as far as possible). and to resolve "."s and ".."s (as far as possible). For non-local paths, adjacent
slashes are preserved.
Note that the case folding rules in \l{RFC 3491}{Nameprep}, which QUrl Note that the case folding rules in \l{RFC 3491}{Nameprep}, which QUrl
conforms to, require host names to always be converted to lower case, conforms to, require host names to always be converted to lower case,
@ -419,10 +420,9 @@
#endif #endif
#include "private/qipaddress_p.h" #include "private/qipaddress_p.h"
#include "qurlquery.h" #include "qurlquery.h"
#include "private/qdir_p.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
extern QString qt_normalizePathSegments(const QString &name, bool allowUncPaths,
bool *ok = nullptr); // qdir.cpp
inline static bool isHex(char c) inline static bool isHex(char c)
{ {
@ -930,7 +930,7 @@ inline void QUrlPrivate::appendPath(QString &appendTo, QUrl::FormattingOptions o
{ {
QString thePath = path; QString thePath = path;
if (options & QUrl::NormalizePathSegments) { if (options & QUrl::NormalizePathSegments) {
thePath = qt_normalizePathSegments(path, false); thePath = qt_normalizePathSegments(path, isLocalFile() ? QDirPrivate::DefaultNormalization : QDirPrivate::RemotePath);
} }
QStringRef thePathRef(&thePath); QStringRef thePathRef(&thePath);

View File

@ -4342,6 +4342,12 @@ QDebug operator<<(QDebug dbg, const QObject *o)
in a QVariant, you can convert them to strings. Likewise, passing them to in a QVariant, you can convert them to strings. Likewise, passing them to
QDebug will print out their names. QDebug will print out their names.
Mind that the enum values are stored as signed \c int in the meta object system.
Registering enumerations with values outside the range of values valid for \c int
will lead to overflows and potentially undefined behavior when accessing them through
the meta object system. QML, for example, does access registered enumerations through
the meta object system.
\sa {Qt's Property System} \sa {Qt's Property System}
*/ */
@ -4393,6 +4399,12 @@ QDebug operator<<(QDebug dbg, const QObject *o)
used in a QVariant, you can convert them to strings. Likewise, passing them used in a QVariant, you can convert them to strings. Likewise, passing them
to QDebug will print out their names. to QDebug will print out their names.
Mind that the enum values are stored as signed \c int in the meta object system.
Registering enumerations with values outside the range of values valid for \c int
will lead to overflows and potentially undefined behavior when accessing them through
the meta object system. QML, for example, does access registered enumerations through
the meta object system.
\sa {Qt's Property System} \sa {Qt's Property System}
*/ */
@ -4450,7 +4462,7 @@ QDebug operator<<(QDebug dbg, const QObject *o)
macro, it must appear in the private section of a class definition. macro, it must appear in the private section of a class definition.
Q_GADGETs can have Q_ENUM, Q_PROPERTY and Q_INVOKABLE, but they cannot have Q_GADGETs can have Q_ENUM, Q_PROPERTY and Q_INVOKABLE, but they cannot have
signals or slots signals or slots.
Q_GADGET makes a class member, \c{staticMetaObject}, available. Q_GADGET makes a class member, \c{staticMetaObject}, available.
\c{staticMetaObject} is of type QMetaObject and provides access to the \c{staticMetaObject} is of type QMetaObject and provides access to the

View File

@ -59,8 +59,7 @@ Q_CORE_EXPORT void QTestPrivate::qSleep(int ms)
#endif #endif
} }
/*! \fn template <typename Functor> bool qWaitFor(Functor predicate, int timeout) /*! \fn template <typename Functor> bool QTest::qWaitFor(Functor predicate, int timeout)
\relates QTest
Waits for \a timeout milliseconds or until the \a predicate returns true. Waits for \a timeout milliseconds or until the \a predicate returns true.
@ -77,8 +76,7 @@ Q_CORE_EXPORT void QTestPrivate::qSleep(int ms)
*/ */
/*! \fn void qWait(int ms) /*! \fn void QTest::qWait(int ms)
\relates QTest
Waits for \a ms milliseconds. While waiting, events will be processed and Waits for \a ms milliseconds. While waiting, events will be processed and
your test will stay responsive to user interface events or network communication. your test will stay responsive to user interface events or network communication.

View File

@ -293,7 +293,7 @@ static void cpuidFeatures07_00(uint &ebx, uint &ecx, uint &edx)
#endif #endif
} }
#ifdef Q_OS_WIN #if defined(Q_OS_WIN) && !(defined(Q_CC_GNU) || defined(Q_CC_GHS))
// fallback overload in case this intrinsic does not exist: unsigned __int64 _xgetbv(unsigned int); // fallback overload in case this intrinsic does not exist: unsigned __int64 _xgetbv(unsigned int);
inline quint64 _xgetbv(__int64) { return 0; } inline quint64 _xgetbv(__int64) { return 0; }
#endif #endif

View File

@ -239,7 +239,8 @@
"sources": [ "sources": [
{ "type": "pkgConfig", "args": "freetype2" }, { "type": "pkgConfig", "args": "freetype2" },
{ "type": "freetype", "libs": "-lfreetype", "condition": "!config.wasm" }, { "type": "freetype", "libs": "-lfreetype", "condition": "!config.wasm" },
{ "libs": "-s USE_FREETYPE=1", "condition": "config.wasm" } { "libs": "-s USE_FREETYPE=1", "condition": "config.wasm" },
{ "libs": "-lfreetype" }
], ],
"use": [ "use": [
{ "lib": "zlib", "condition": "features.system-zlib" } { "lib": "zlib", "condition": "features.system-zlib" }
@ -1436,7 +1437,7 @@
}, },
"eglfs_x11": { "eglfs_x11": {
"label": "EGLFS X11", "label": "EGLFS X11",
"condition": "features.eglfs && features.xcb && features.xcb-xlib && features.egl_x11", "condition": "features.eglfs && features.xcb-xlib && features.egl_x11",
"output": [ "privateFeature" ] "output": [ "privateFeature" ]
}, },
"gif": { "gif": {
@ -1569,7 +1570,6 @@
}, },
"xcb-xlib": { "xcb-xlib": {
"label": "XCB Xlib", "label": "XCB Xlib",
"emitIf": "features.xcb",
"condition": "features.xlib && libs.xcb_xlib", "condition": "features.xlib && libs.xcb_xlib",
"output": [ "privateFeature" ] "output": [ "privateFeature" ]
}, },

View File

@ -54,7 +54,10 @@ exampledirs += ../../../examples/gui \
imagedirs += images \ imagedirs += images \
../../../examples/gui/doc/images \ ../../../examples/gui/doc/images \
../../../doc/src/images \ ../../../doc/src/images
# Included in qttestlib.qdocconf instead
excludefiles += ../kernel/qtestsupport_gui.cpp
manifestmeta.highlighted.names = "QtGui/Analog Clock Window Example" manifestmeta.highlighted.names = "QtGui/Analog Clock Window Example"

View File

@ -188,7 +188,7 @@ static bool read_dib_infoheader(QDataStream &s, BMP_INFOHDR &bi)
if (!(comp == BMP_RGB || (nbits == 4 && comp == BMP_RLE4) || if (!(comp == BMP_RGB || (nbits == 4 && comp == BMP_RLE4) ||
(nbits == 8 && comp == BMP_RLE8) || ((nbits == 16 || nbits == 32) && comp == BMP_BITFIELDS))) (nbits == 8 && comp == BMP_RLE8) || ((nbits == 16 || nbits == 32) && comp == BMP_BITFIELDS)))
return false; // weird compression type return false; // weird compression type
if (bi.biWidth < 0 || quint64(bi.biWidth) * qAbs(bi.biHeight) > 16384 * 16384) if (bi.biWidth <= 0 || !bi.biHeight || quint64(bi.biWidth) * qAbs(bi.biHeight) > 16384 * 16384)
return false; return false;
return true; return true;

View File

@ -3570,7 +3570,7 @@ void QImage::rgbSwapped_inplace()
The loader attempts to read the image using the specified \a format, e.g., The loader attempts to read the image using the specified \a format, e.g.,
PNG or JPG. If \a format is not specified (which is the default), it is PNG or JPG. If \a format is not specified (which is the default), it is
auto-detected based on the file's suffix and header. For details, see auto-detected based on the file's suffix and header. For details, see
{QImageReader::setAutoDetectImageFormat()}{QImageReader}. QImageReader::setAutoDetectImageFormat().
The file name can either refer to an actual file on disk or to one The file name can either refer to an actual file on disk or to one
of the application's embedded resources. See the of the application's embedded resources. See the

View File

@ -313,9 +313,12 @@ void QHighDpiScaling::updateHighDpiScaling()
} }
m_active = m_globalScalingActive || m_screenFactorSet || m_pixelDensityScalingActive; m_active = m_globalScalingActive || m_screenFactorSet || m_pixelDensityScalingActive;
QPlatformScreen *primaryScreen = QGuiApplication::primaryScreen()->handle(); QScreen *primaryScreen = QGuiApplication::primaryScreen();
qreal sf = screenSubfactor(primaryScreen); if (!primaryScreen)
QDpi primaryDpi = primaryScreen->logicalDpi(); return;
QPlatformScreen *platformScreen = primaryScreen->handle();
qreal sf = screenSubfactor(platformScreen);
QDpi primaryDpi = platformScreen->logicalDpi();
m_logicalDpi = QDpi(primaryDpi.first / sf, primaryDpi.second / sf); m_logicalDpi = QDpi(primaryDpi.first / sf, primaryDpi.second / sf);
} }

View File

@ -110,7 +110,7 @@ public:
virtual bool isActive() const; virtual bool isActive() const;
virtual bool isAncestorOf(const QPlatformWindow *child) const; virtual bool isAncestorOf(const QPlatformWindow *child) const;
virtual bool isEmbedded() const; virtual bool isEmbedded() const;
virtual bool isForeignWindow() const { return window()->type() == Qt::ForeignWindow; }; virtual bool isForeignWindow() const { return false; };
virtual QPoint mapToGlobal(const QPoint &pos) const; virtual QPoint mapToGlobal(const QPoint &pos) const;
virtual QPoint mapFromGlobal(const QPoint &pos) const; virtual QPoint mapFromGlobal(const QPoint &pos) const;

View File

@ -44,23 +44,21 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
/*! \fn bool qWaitForWindowActive(QWindow *window, int timeout) /*!
\relates QTest
\since 5.0 \since 5.0
Waits for \a timeout milliseconds or until the \a window is active. Waits for \a timeout milliseconds or until the \a window is active.
Returns \c true if \c window is active within \a timeout milliseconds, otherwise returns \c false. Returns \c true if \c window is active within \a timeout milliseconds, otherwise returns \c false.
\sa QTest::qWaitForWindowExposed(), QWindow::isActive() \sa qWaitForWindowExposed(), QWindow::isActive()
*/ */
Q_GUI_EXPORT bool QTest::qWaitForWindowActive(QWindow *window, int timeout) Q_GUI_EXPORT bool QTest::qWaitForWindowActive(QWindow *window, int timeout)
{ {
return QTest::qWaitFor([&]() { return window->isActive(); }, timeout); return QTest::qWaitFor([&]() { return window->isActive(); }, timeout);
} }
/*! \fn bool qWaitForWindowExposed(QWindow *window, int timeout) /*!
\relates QTest
\since 5.0 \since 5.0
Waits for \a timeout milliseconds or until the \a window is exposed. Waits for \a timeout milliseconds or until the \a window is exposed.
@ -73,7 +71,7 @@ Q_GUI_EXPORT bool QTest::qWaitForWindowActive(QWindow *window, int timeout)
area is completely covered by other windows, or if the window is otherwise not visible. This function area is completely covered by other windows, or if the window is otherwise not visible. This function
will then time out when waiting for such a window. will then time out when waiting for such a window.
\sa QTest::qWaitForWindowActive(), QWindow::isExposed() \sa qWaitForWindowActive(), QWindow::isExposed()
*/ */
Q_GUI_EXPORT bool QTest::qWaitForWindowExposed(QWindow *window, int timeout) Q_GUI_EXPORT bool QTest::qWaitForWindowExposed(QWindow *window, int timeout)
{ {

View File

@ -919,8 +919,7 @@ void QWindow::setFlag(Qt::WindowType flag, bool on)
*/ */
Qt::WindowType QWindow::type() const Qt::WindowType QWindow::type() const
{ {
Q_D(const QWindow); return static_cast<Qt::WindowType>(int(flags() & Qt::WindowType_Mask));
return static_cast<Qt::WindowType>(int(d->windowFlags & Qt::WindowType_Mask));
} }
/*! /*!

View File

@ -225,7 +225,7 @@ template<bool RGBA>
static inline void convertARGBFromRGBA64PM_sse4(uint *buffer, const QRgba64 *src, int count) static inline void convertARGBFromRGBA64PM_sse4(uint *buffer, const QRgba64 *src, int count)
{ {
int i = 0; int i = 0;
const __m128i alphaMask = _mm_set1_epi64x(Q_UINT64_C(0xffff) << 48); const __m128i alphaMask = _mm_set1_epi64x(qint64(Q_UINT64_C(0xffff) << 48));
const __m128i alphaMask32 = _mm_set1_epi32(0xff000000); const __m128i alphaMask32 = _mm_set1_epi32(0xff000000);
const __m128i rgbaMask = _mm_setr_epi8(2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15); const __m128i rgbaMask = _mm_setr_epi8(2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15);
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();

View File

@ -1954,13 +1954,14 @@ void QPdfEnginePrivate::writePage()
"/Contents %d 0 R\n" "/Contents %d 0 R\n"
"/Resources %d 0 R\n" "/Resources %d 0 R\n"
"/Annots %d 0 R\n" "/Annots %d 0 R\n"
"/MediaBox [0 0 %f %f]\n", "/MediaBox [0 0 %s %s]\n",
pageRoot, pageStream, resources, annots, pageRoot, pageStream, resources, annots,
// make sure we use the pagesize from when we started the page, since the user may have changed it // make sure we use the pagesize from when we started the page, since the user may have changed it
currentPage->pageSize.width() / userUnit, currentPage->pageSize.height() / userUnit); QByteArray::number(currentPage->pageSize.width() / userUnit, 'f').constData(),
QByteArray::number(currentPage->pageSize.height() / userUnit, 'f').constData());
if (pdfVersion >= QPdfEngine::Version_1_6) if (pdfVersion >= QPdfEngine::Version_1_6)
xprintf("/UserUnit %f\n", userUnit); xprintf("/UserUnit %s\n", QByteArray::number(userUnit, 'f').constData());
xprintf(">>\n" xprintf(">>\n"
"endobj\n"); "endobj\n");

View File

@ -411,6 +411,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
} else if (!region.isEmpty()){ } else if (!region.isEmpty()){
funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId); funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId);
QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &d_ptr->needsSwizzle, &d_ptr->premultiplied); QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &d_ptr->needsSwizzle, &d_ptr->premultiplied);
graphicsBuffer->unlock();
} }
if (graphicsBuffer->origin() == QPlatformGraphicsBuffer::OriginBottomLeft) if (graphicsBuffer->origin() == QPlatformGraphicsBuffer::OriginBottomLeft)

View File

@ -1972,14 +1972,18 @@ void QTextEngine::shape(int item) const
} }
// fix log clusters to point to the previous glyph, as the object doesn't have a glyph of it's own. // fix log clusters to point to the previous glyph, as the object doesn't have a glyph of it's own.
// This is required so that all entries in the array get initialized and are ordered correctly. // This is required so that all entries in the array get initialized and are ordered correctly.
if (layoutData->logClustersPtr) {
ushort *lc = logClusters(&li); ushort *lc = logClusters(&li);
*lc = item ? lc[-1] : 0; *lc = (lc != layoutData->logClustersPtr) ? lc[-1] : 0;
}
} else if (li.analysis.flags == QScriptAnalysis::Tab) { } else if (li.analysis.flags == QScriptAnalysis::Tab) {
// set up at least the ascent/descent/leading of the script item for the tab // set up at least the ascent/descent/leading of the script item for the tab
fontEngine(li, &li.ascent, &li.descent, &li.leading); fontEngine(li, &li.ascent, &li.descent, &li.leading);
// see the comment above // see the comment above
if (layoutData->logClustersPtr) {
ushort *lc = logClusters(&li); ushort *lc = logClusters(&li);
*lc = item ? lc[-1] : 0; *lc = (lc != layoutData->logClustersPtr) ? lc[-1] : 0;
}
} else { } else {
shapeText(item); shapeText(item);
} }

View File

@ -464,8 +464,10 @@ static QNetworkInterface::InterfaceType probeIfType(int socket, int iftype, stru
case IFM_ETHER: case IFM_ETHER:
return QNetworkInterface::Ethernet; return QNetworkInterface::Ethernet;
#ifdef IFM_FDDI
case IFM_FDDI: case IFM_FDDI:
return QNetworkInterface::Fddi; return QNetworkInterface::Fddi;
#endif
case IFM_IEEE80211: case IFM_IEEE80211:
return QNetworkInterface::Ieee80211; return QNetworkInterface::Ieee80211;

View File

@ -75,7 +75,7 @@ namespace QPasswordDigestor {
\a salt must always be 8 bytes long! \a salt must always be 8 bytes long!
\note This function is provided for use with legacy applications and all \note This function is provided for use with legacy applications and all
new applications are recommended to use \l {pbkdf2} {PBKDF2}. new applications are recommended to use \l {deriveKeyPbkdf2} {PBKDF2}.
\sa deriveKeyPbkdf2, QCryptographicHash, QCryptographicHash::hashLength \sa deriveKeyPbkdf2, QCryptographicHash, QCryptographicHash::hashLength
*/ */

View File

@ -49,7 +49,9 @@ class QEglFSFunctions
{ {
public: public:
typedef void (*LoadKeymapType)(const QString &filename); typedef void (*LoadKeymapType)(const QString &filename);
typedef void (*SwitchLangType)();
static QByteArray loadKeymapTypeIdentifier() { return QByteArrayLiteral("EglFSLoadKeymap"); } static QByteArray loadKeymapTypeIdentifier() { return QByteArrayLiteral("EglFSLoadKeymap"); }
static QByteArray switchLangTypeIdentifier() { return QByteArrayLiteral("EglFSSwitchLang"); }
static void loadKeymap(const QString &filename) static void loadKeymap(const QString &filename)
{ {
@ -58,6 +60,13 @@ public:
func(filename); func(filename);
} }
static void switchLang()
{
SwitchLangType func = reinterpret_cast<SwitchLangType>(QGuiApplication::platformFunction(switchLangTypeIdentifier()));
if (func)
func();
}
typedef int (*Vsp2AddLayerType)(const QScreen *screen, int dmabufFd, const QSize &size, const QPoint &position, uint drmPixelFormat, uint bytesPerLine); typedef int (*Vsp2AddLayerType)(const QScreen *screen, int dmabufFd, const QSize &size, const QPoint &position, uint drmPixelFormat, uint bytesPerLine);
static QByteArray vsp2AddLayerTypeIdentifier() { return QByteArrayLiteral("EglFSVsp2AddLayer"); } static QByteArray vsp2AddLayerTypeIdentifier() { return QByteArrayLiteral("EglFSVsp2AddLayer"); }

View File

@ -66,6 +66,21 @@
support, this function will have no effect. support, this function will have no effect.
*/ */
/*!
\fn void QEglFSFunctions::switchLang()
Switches between English and other language when the keymap is loaded.
Usually the keymap contains two languages: English and national. When
you load the keymap, English is selected by default. This function allows
to switch between these languages.
\note This is functional only when the evdev keyboard support code is
compiled in to the platform plugin. When using external generic plugins via
the \c{-plugin} argument, or when the environment variable
\c{QT_QPA_EGLFS_DISABLE_INPUT} is set or when building Qt without evdev
support, this function will have no effect.
*/
/*! /*!
\fn int QEglFSFunctions::vsp2AddLayer(const QScreen *screen, int dmabufFd, const QSize &size, const QPoint &position, uint drmPixelFormat, uint bytesPerLine) \fn int QEglFSFunctions::vsp2AddLayer(const QScreen *screen, int dmabufFd, const QSize &size, const QPoint &position, uint drmPixelFormat, uint bytesPerLine)
\internal \internal

View File

@ -0,0 +1 @@
HEADERS += $$PWD/qlinuxfbfunctions.h

View File

@ -0,0 +1,74 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QLINUXFBFUNCTIONS_H
#define QLINUXFBFUNCTIONS_H
#include <QtCore/QByteArray>
#include <QtGui/QGuiApplication>
QT_BEGIN_NAMESPACE
class QLinuxFbFunctions
{
public:
typedef void (*LoadKeymapType)(const QString &filename);
typedef void (*SwitchLangType)();
static QByteArray loadKeymapTypeIdentifier() { return QByteArrayLiteral("LinuxFbLoadKeymap"); }
static QByteArray switchLangTypeIdentifier() { return QByteArrayLiteral("LinuxFbSwitchLang"); }
static void loadKeymap(const QString &filename)
{
LoadKeymapType func = reinterpret_cast<LoadKeymapType>(QGuiApplication::platformFunction(loadKeymapTypeIdentifier()));
if (func)
func(filename);
}
static void switchLang()
{
SwitchLangType func = reinterpret_cast<SwitchLangType>(QGuiApplication::platformFunction(switchLangTypeIdentifier()));
if (func)
func();
}
};
QT_END_NAMESPACE
#endif // QLINUXFBFUNCTIONS_H

View File

@ -0,0 +1,82 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\class QLinuxFbFunctions
\inmodule QtPlatformHeaders
\brief The QLinuxFbFunctions class is an inline class containing
platform-specific functionality for the linuxfb platform plugin that is
typically used on systems running Embedded Linux or Android.
\note There is no binary compatibility guarantee for this class,
meaning that an application using it is only guaranteed to work with the Qt
version it was developed against.
*/
/*!
\typedef QLinuxFbFunctions::LoadKeymapType
Function type for loadKeymap.
*/
/*!
\fn QByteArray QLinuxFbFunctions::loadKeymapTypeIdentifier()
\return the identifier that can be passed to
QGuiApplication::platformFunction() to query the entry point for the
loadKeymap function implementation.
*/
/*!
\fn void QLinuxFbFunctions::loadKeymap(const QString &filename)
Loads and switches to the keymap from \a filename. When \a filename is
empty, the default keymap, which is either the built-on one or the keymap
given in the plugin specification, is restored.
\note This is functional only when the evdev keyboard support code is
compiled in to the platform plugin. When using external generic plugins via
the \c{-plugin} argument, or when the environment variable
\c{QT_QPA_FB_DISABLE_INPUT} is set or when building Qt without evdev
support, this function will have no effect.
*/
/*!
\fn void QLinuxFbFunctions::switchLang()
Switches between English and other language when the keymap is loaded.
Usually the keymap contains two languages: English and national. When
you load the keymap, English is selected by default. This function allows
to switch between these languages.
\note This is functional only when the evdev keyboard support code is
compiled in to the platform plugin. When using external generic plugins via
the \c{-plugin} argument, or when the environment variable
\c{QT_QPA_FB_DISABLE_INPUT} is set or when building Qt without evdev
support, this function will have no effect.
*/

View File

@ -10,6 +10,7 @@ include(windowsfunctions/windowsfunctions.pri)
include(helper/helper.pri) include(helper/helper.pri)
include(cocoafunctions/cocoafunctions.pri) include(cocoafunctions/cocoafunctions.pri)
include(waylandfunctions/waylandfunctions.pri) include(waylandfunctions/waylandfunctions.pri)
include(linuxfbfunctions/linuxfbfunctions.pri)
QMAKE_DOCS = $$PWD/doc/qtplatformheaders.qdocconf QMAKE_DOCS = $$PWD/doc/qtplatformheaders.qdocconf

View File

@ -76,7 +76,7 @@ void QFdContainer::reset() Q_DECL_NOTHROW
QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, QFdContainer &fd, bool disableZap, bool enableCompose, const QString &keymapFile) QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, QFdContainer &fd, bool disableZap, bool enableCompose, const QString &keymapFile)
: m_device(device), m_fd(fd.release()), m_notify(nullptr), : m_device(device), m_fd(fd.release()), m_notify(nullptr),
m_modifiers(0), m_composing(0), m_dead_unicode(0xffff), m_modifiers(0), m_composing(0), m_dead_unicode(0xffff),
m_no_zap(disableZap), m_do_compose(enableCompose), m_langLock(0), m_no_zap(disableZap), m_do_compose(enableCompose),
m_keymap(0), m_keymap_size(0), m_keycompose(0), m_keycompose_size(0) m_keymap(0), m_keymap_size(0), m_keycompose(0), m_keycompose_size(0)
{ {
qCDebug(qLcEvdevKey) << "Create keyboard handler with for device" << device; qCDebug(qLcEvdevKey) << "Create keyboard handler with for device" << device;
@ -253,6 +253,8 @@ QEvdevKeyboardHandler::KeycodeAction QEvdevKeyboardHandler::processKeycode(quint
quint8 testmods = m_modifiers; quint8 testmods = m_modifiers;
if (m_locks[0] /*CapsLock*/ && (m->flags & QEvdevKeyboardMap::IsLetter)) if (m_locks[0] /*CapsLock*/ && (m->flags & QEvdevKeyboardMap::IsLetter))
testmods ^= QEvdevKeyboardMap::ModShift; testmods ^= QEvdevKeyboardMap::ModShift;
if (m_langLock)
testmods ^= QEvdevKeyboardMap::ModAltGr;
if (m->modifiers == testmods) if (m->modifiers == testmods)
map_withmod = m; map_withmod = m;
} }
@ -509,6 +511,8 @@ void QEvdevKeyboardHandler::unloadKeymap()
m_locks[2] = 1; m_locks[2] = 1;
qCDebug(qLcEvdevKey, "numlock=%d , capslock=%d, scrolllock=%d", m_locks[1], m_locks[0], m_locks[2]); qCDebug(qLcEvdevKey, "numlock=%d , capslock=%d, scrolllock=%d", m_locks[1], m_locks[0], m_locks[2]);
} }
m_langLock = 0;
} }
bool QEvdevKeyboardHandler::loadKeymap(const QString &file) bool QEvdevKeyboardHandler::loadKeymap(const QString &file)
@ -570,4 +574,9 @@ bool QEvdevKeyboardHandler::loadKeymap(const QString &file)
return true; return true;
} }
void QEvdevKeyboardHandler::switchLang()
{
m_langLock ^= 1;
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -192,6 +192,8 @@ public:
void readKeycode(); void readKeycode();
KeycodeAction processKeycode(quint16 keycode, bool pressed, bool autorepeat); KeycodeAction processKeycode(quint16 keycode, bool pressed, bool autorepeat);
void switchLang();
private: private:
void processKeyEvent(int nativecode, int unicode, int qtcode, void processKeyEvent(int nativecode, int unicode, int qtcode,
Qt::KeyboardModifiers modifiers, bool isPress, bool autoRepeat); Qt::KeyboardModifiers modifiers, bool isPress, bool autoRepeat);
@ -206,6 +208,7 @@ private:
quint8 m_locks[3]; quint8 m_locks[3];
int m_composing; int m_composing;
quint16 m_dead_unicode; quint16 m_dead_unicode;
quint8 m_langLock;
bool m_no_zap; bool m_no_zap;
bool m_do_compose; bool m_do_compose;

View File

@ -153,4 +153,10 @@ void QEvdevKeyboardManager::loadKeymap(const QString &file)
} }
} }
void QEvdevKeyboardManager::switchLang()
{
foreach (QEvdevKeyboardHandler *handler, m_keyboards)
handler->switchLang();
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -68,6 +68,7 @@ public:
~QEvdevKeyboardManager(); ~QEvdevKeyboardManager();
void loadKeymap(const QString &file); void loadKeymap(const QString &file);
void switchLang();
void addKeyboard(const QString &deviceNode = QString()); void addKeyboard(const QString &deviceNode = QString());
void removeKeyboard(const QString &deviceNode); void removeKeyboard(const QString &deviceNode);

View File

@ -243,7 +243,7 @@ public:
// bool setConnections(); // bool setConnections();
Q_SIGNALS: Q_SIGNALS:
void propertiesChanged(QMap <QString,QVariant>); void propertiesChanged(QMap<QString,QVariant>);
void propertiesReady(); void propertiesReady();
private Q_SLOTS: private Q_SLOTS:

View File

@ -99,13 +99,12 @@ static jfieldID m_selectionStartFieldID = 0;
static jfieldID m_startOffsetFieldID = 0; static jfieldID m_startOffsetFieldID = 0;
static jfieldID m_textFieldID = 0; static jfieldID m_textFieldID = 0;
Q_DECLARE_METATYPE(std::function<void()>)
static void runOnQtThread(const std::function<void()> &func) static void runOnQtThread(const std::function<void()> &func)
{ {
const bool block = QGuiApplication::applicationState() >= Qt::ApplicationInactive; AndroidDeadlockProtector protector;
QMetaObject::invokeMethod(m_androidInputContext, "safeCall", if (!protector.acquire())
block ? Qt::BlockingQueuedConnection : Qt::QueuedConnection, Q_ARG(std::function<void()>, func)); return;
QMetaObject::invokeMethod(m_androidInputContext, "safeCall", Qt::BlockingQueuedConnection, Q_ARG(std::function<void()>, func));
} }
static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/) static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
@ -116,7 +115,7 @@ static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ BEGINBATCH"); qDebug("@@@ BEGINBATCH");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&res]{res = m_androidInputContext->beginBatchEdit();}); runOnQtThread([&res]{res = m_androidInputContext->beginBatchEdit();});
return res; return res;
} }
@ -130,7 +129,7 @@ static jboolean endBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
qDebug("@@@ ENDBATCH"); qDebug("@@@ ENDBATCH");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&res]{res = m_androidInputContext->endBatchEdit();}); runOnQtThread([&res]{res = m_androidInputContext->endBatchEdit();});
return res; return res;
} }
@ -149,7 +148,7 @@ static jboolean commitText(JNIEnv *env, jobject /*thiz*/, jstring text, jint new
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ COMMIT" << str << newCursorPosition; qDebug() << "@@@ COMMIT" << str << newCursorPosition;
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->commitText(str, newCursorPosition);}); runOnQtThread([&]{res = m_androidInputContext->commitText(str, newCursorPosition);});
return res; return res;
} }
@ -162,7 +161,7 @@ static jboolean deleteSurroundingText(JNIEnv */*env*/, jobject /*thiz*/, jint le
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ DELETE" << leftLength << rightLength; qDebug() << "@@@ DELETE" << leftLength << rightLength;
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->deleteSurroundingText(leftLength, rightLength);}); runOnQtThread([&]{res = m_androidInputContext->deleteSurroundingText(leftLength, rightLength);});
return res; return res;
} }
@ -175,7 +174,7 @@ static jboolean finishComposingText(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ FINISH"); qDebug("@@@ FINISH");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->finishComposingText();}); runOnQtThread([&]{res = m_androidInputContext->finishComposingText();});
return res; return res;
} }
@ -185,7 +184,7 @@ static jint getCursorCapsMode(JNIEnv */*env*/, jobject /*thiz*/, jint reqModes)
if (!m_androidInputContext) if (!m_androidInputContext)
return 0; return 0;
jboolean res; jint res = 0;
runOnQtThread([&]{res = m_androidInputContext->getCursorCapsMode(reqModes);}); runOnQtThread([&]{res = m_androidInputContext->getCursorCapsMode(reqModes);});
return res; return res;
} }
@ -270,7 +269,7 @@ static jboolean setComposingText(JNIEnv *env, jobject /*thiz*/, jstring text, ji
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SET" << str << newCursorPosition; qDebug() << "@@@ SET" << str << newCursorPosition;
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->setComposingText(str, newCursorPosition);}); runOnQtThread([&]{res = m_androidInputContext->setComposingText(str, newCursorPosition);});
return res; return res;
} }
@ -283,7 +282,7 @@ static jboolean setComposingRegion(JNIEnv */*env*/, jobject /*thiz*/, jint start
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SETR" << start << end; qDebug() << "@@@ SETR" << start << end;
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->setComposingRegion(start, end);}); runOnQtThread([&]{res = m_androidInputContext->setComposingRegion(start, end);});
return res; return res;
} }
@ -297,7 +296,7 @@ static jboolean setSelection(JNIEnv */*env*/, jobject /*thiz*/, jint start, jint
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SETSEL" << start << end; qDebug() << "@@@ SETSEL" << start << end;
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->setSelection(start, end);}); runOnQtThread([&]{res = m_androidInputContext->setSelection(start, end);});
return res; return res;
@ -311,7 +310,7 @@ static jboolean selectAll(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ SELALL"); qDebug("@@@ SELALL");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->selectAll();}); runOnQtThread([&]{res = m_androidInputContext->selectAll();});
return res; return res;
} }
@ -324,7 +323,7 @@ static jboolean cut(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@"); qDebug("@@@");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->cut();}); runOnQtThread([&]{res = m_androidInputContext->cut();});
return res; return res;
} }
@ -337,7 +336,7 @@ static jboolean copy(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@"); qDebug("@@@");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->copy();}); runOnQtThread([&]{res = m_androidInputContext->copy();});
return res; return res;
} }
@ -350,7 +349,7 @@ static jboolean copyURL(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@"); qDebug("@@@");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->copyURL();}); runOnQtThread([&]{res = m_androidInputContext->copyURL();});
return res; return res;
} }
@ -363,7 +362,7 @@ static jboolean paste(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ PASTE"); qDebug("@@@ PASTE");
#endif #endif
jboolean res; jboolean res = JNI_FALSE;
runOnQtThread([&]{res = m_androidInputContext->paste();}); runOnQtThread([&]{res = m_androidInputContext->paste();});
return res; return res;
} }
@ -516,7 +515,6 @@ QAndroidInputContext::QAndroidInputContext()
m_handleMode = Hidden; m_handleMode = Hidden;
updateSelectionHandles(); updateSelectionHandles();
}); });
qRegisterMetaType<std::function<void()>>();
} }
QAndroidInputContext::~QAndroidInputContext() QAndroidInputContext::~QAndroidInputContext()

View File

@ -429,6 +429,8 @@ QFunctionPointer QEglFSIntegration::platformFunction(const QByteArray &function)
#if QT_CONFIG(evdev) #if QT_CONFIG(evdev)
if (function == QEglFSFunctions::loadKeymapTypeIdentifier()) if (function == QEglFSFunctions::loadKeymapTypeIdentifier())
return QFunctionPointer(loadKeymapStatic); return QFunctionPointer(loadKeymapStatic);
else if (function == QEglFSFunctions::switchLangTypeIdentifier())
return QFunctionPointer(switchLangStatic);
#endif #endif
return qt_egl_device_integration()->platformFunction(function); return qt_egl_device_integration()->platformFunction(function);
@ -447,6 +449,17 @@ void QEglFSIntegration::loadKeymapStatic(const QString &filename)
#endif #endif
} }
void QEglFSIntegration::switchLangStatic()
{
#if QT_CONFIG(evdev)
QEglFSIntegration *self = static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration());
if (self->m_kbdMgr)
self->m_kbdMgr->switchLang();
else
qWarning("QEglFSIntegration: Cannot switch language, no keyboard handler found");
#endif
}
void QEglFSIntegration::createInputHandlers() void QEglFSIntegration::createInputHandlers()
{ {
#if QT_CONFIG(libinput) #if QT_CONFIG(libinput)

View File

@ -110,6 +110,7 @@ private:
EGLNativeDisplayType nativeDisplay() const; EGLNativeDisplayType nativeDisplay() const;
void createInputHandlers(); void createInputHandlers();
static void loadKeymapStatic(const QString &filename); static void loadKeymapStatic(const QString &filename);
static void switchLangStatic();
EGLDisplay m_display; EGLDisplay m_display;
QPlatformInputContext *m_inputContext; QPlatformInputContext *m_inputContext;

View File

@ -118,6 +118,8 @@ QPlatformCursor *QEglFSKmsGbmIntegration::createCursor(QPlatformScreen *screen)
qCDebug(qLcEglfsKmsDebug, "Using plain OpenGL mouse cursor"); qCDebug(qLcEglfsKmsDebug, "Using plain OpenGL mouse cursor");
return new QEglFSCursor(screen); return new QEglFSCursor(screen);
} }
#else
Q_UNUSED(screen);
#endif #endif
return nullptr; return nullptr;
} }

View File

@ -290,6 +290,8 @@ QPlatformCursor *QEglFSKmsEglDeviceIntegration::createCursor(QPlatformScreen *sc
#if QT_CONFIG(opengl) #if QT_CONFIG(opengl)
if (screenConfig()->separateScreens()) if (screenConfig()->separateScreens())
return new QEglFSCursor(screen); return new QEglFSCursor(screen);
#else
Q_UNUSED(screen);
#endif #endif
return nullptr; return nullptr;
} }

View File

@ -65,7 +65,7 @@ void QEglFSVivIntegration::platformInit()
VivanteInit(); VivanteInit();
mNativeDisplay = fbGetDisplay(); mNativeDisplay = fbGetDisplay();
#else #else
mNativeDisplay = fbGetDisplayByIndex(framebufferIndex()); mNativeDisplay = static_cast<EGLNativeDisplayType>(fbGetDisplayByIndex(framebufferIndex()));
#endif #endif
fbGetDisplayGeometry(mNativeDisplay, &width, &height); fbGetDisplayGeometry(mNativeDisplay, &width, &height);
@ -88,7 +88,7 @@ EGLNativeWindowType QEglFSVivIntegration::createNativeWindow(QPlatformWindow *wi
Q_UNUSED(window) Q_UNUSED(window)
Q_UNUSED(format) Q_UNUSED(format)
EGLNativeWindowType eglWindow = fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height()); EGLNativeWindowType eglWindow = static_cast<EGLNativeWindowType>(fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height()));
return eglWindow; return eglWindow;
} }

View File

@ -60,7 +60,7 @@ void QEglFSVivWaylandIntegration::platformInit()
} }
mWaylandDisplay = wl_display_create(); mWaylandDisplay = wl_display_create();
mNativeDisplay = fbGetDisplay(mWaylandDisplay); mNativeDisplay = static_cast<EGLNativeDisplayType>(fbGetDisplay(mWaylandDisplay));
fbGetDisplayGeometry(mNativeDisplay, &width, &height); fbGetDisplayGeometry(mNativeDisplay, &width, &height);
mScreenSize.setHeight(height); mScreenSize.setHeight(height);
mScreenSize.setWidth(width); mScreenSize.setWidth(width);
@ -81,7 +81,7 @@ EGLNativeWindowType QEglFSVivWaylandIntegration::createNativeWindow(QPlatformWin
Q_UNUSED(window) Q_UNUSED(window)
Q_UNUSED(format) Q_UNUSED(format)
EGLNativeWindowType eglWindow = fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height()); EGLNativeWindowType eglWindow = static_cast<EGLNativeWindowType>(fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height()));
return eglWindow; return eglWindow;
} }

View File

@ -69,12 +69,15 @@
#include <QtInputSupport/private/qtslib_p.h> #include <QtInputSupport/private/qtslib_p.h>
#endif #endif
#include <QtPlatformHeaders/qlinuxfbfunctions.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
QLinuxFbIntegration::QLinuxFbIntegration(const QStringList &paramList) QLinuxFbIntegration::QLinuxFbIntegration(const QStringList &paramList)
: m_primaryScreen(nullptr), : m_primaryScreen(nullptr),
m_fontDb(new QGenericUnixFontDatabase), m_fontDb(new QGenericUnixFontDatabase),
m_services(new QGenericUnixServices) m_services(new QGenericUnixServices),
m_kbdMgr(0)
{ {
#if QT_CONFIG(kms) #if QT_CONFIG(kms)
if (qEnvironmentVariableIntValue("QT_QPA_FB_DRM") != 0) if (qEnvironmentVariableIntValue("QT_QPA_FB_DRM") != 0)
@ -98,8 +101,6 @@ void QLinuxFbIntegration::initialize()
m_inputContext = QPlatformInputContextFactory::create(); m_inputContext = QPlatformInputContextFactory::create();
m_nativeInterface.reset(new QPlatformNativeInterface);
m_vtHandler.reset(new QFbVtHandler); m_vtHandler.reset(new QFbVtHandler);
if (!qEnvironmentVariableIntValue("QT_QPA_FB_DISABLE_INPUT")) if (!qEnvironmentVariableIntValue("QT_QPA_FB_DISABLE_INPUT"))
@ -163,7 +164,7 @@ void QLinuxFbIntegration::createInputHandlers()
#endif #endif
#if QT_CONFIG(evdev) #if QT_CONFIG(evdev)
new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this); m_kbdMgr = new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this);
new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this); new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this);
#if QT_CONFIG(tslib) #if QT_CONFIG(tslib)
if (!useTslib) if (!useTslib)
@ -174,7 +175,45 @@ void QLinuxFbIntegration::createInputHandlers()
QPlatformNativeInterface *QLinuxFbIntegration::nativeInterface() const QPlatformNativeInterface *QLinuxFbIntegration::nativeInterface() const
{ {
return m_nativeInterface.data(); return const_cast<QLinuxFbIntegration *>(this);
}
QFunctionPointer QLinuxFbIntegration::platformFunction(const QByteArray &function) const
{
#if QT_CONFIG(evdev)
if (function == QLinuxFbFunctions::loadKeymapTypeIdentifier())
return QFunctionPointer(loadKeymapStatic);
else if (function == QLinuxFbFunctions::switchLangTypeIdentifier())
return QFunctionPointer(switchLangStatic);
#else
Q_UNUSED(function)
#endif
return 0;
}
void QLinuxFbIntegration::loadKeymapStatic(const QString &filename)
{
#if QT_CONFIG(evdev)
QLinuxFbIntegration *self = static_cast<QLinuxFbIntegration *>(QGuiApplicationPrivate::platformIntegration());
if (self->m_kbdMgr)
self->m_kbdMgr->loadKeymap(filename);
else
qWarning("QLinuxFbIntegration: Cannot load keymap, no keyboard handler found");
#else
Q_UNUSED(filename);
#endif
}
void QLinuxFbIntegration::switchLangStatic()
{
#if QT_CONFIG(evdev)
QLinuxFbIntegration *self = static_cast<QLinuxFbIntegration *>(QGuiApplicationPrivate::platformIntegration());
if (self->m_kbdMgr)
self->m_kbdMgr->switchLang();
else
qWarning("QLinuxFbIntegration: Cannot switch language, no keyboard handler found");
#endif
} }
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE
class QAbstractEventDispatcher; class QAbstractEventDispatcher;
class QFbScreen; class QFbScreen;
class QFbVtHandler; class QFbVtHandler;
class QEvdevKeyboardManager;
class QLinuxFbIntegration : public QPlatformIntegration, public QPlatformNativeInterface class QLinuxFbIntegration : public QPlatformIntegration, public QPlatformNativeInterface
{ {
@ -71,15 +72,20 @@ public:
QList<QPlatformScreen *> screens() const; QList<QPlatformScreen *> screens() const;
QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE;
private: private:
void createInputHandlers(); void createInputHandlers();
static void loadKeymapStatic(const QString &filename);
static void switchLangStatic();
QFbScreen *m_primaryScreen; QFbScreen *m_primaryScreen;
QPlatformInputContext *m_inputContext; QPlatformInputContext *m_inputContext;
QScopedPointer<QPlatformFontDatabase> m_fontDb; QScopedPointer<QPlatformFontDatabase> m_fontDb;
QScopedPointer<QPlatformServices> m_services; QScopedPointer<QPlatformServices> m_services;
QScopedPointer<QFbVtHandler> m_vtHandler; QScopedPointer<QFbVtHandler> m_vtHandler;
QScopedPointer<QPlatformNativeInterface> m_nativeInterface;
QEvdevKeyboardManager *m_kbdMgr;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -1115,8 +1115,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::DisplayChangedEvent: case QtWindows::DisplayChangedEvent:
if (QWindowsTheme *t = QWindowsTheme::instance()) if (QWindowsTheme *t = QWindowsTheme::instance())
t->displayChanged(); t->displayChanged();
QWindowsWindow::displayChanged();
return d->m_screenManager.handleDisplayChange(wParam, lParam); return d->m_screenManager.handleDisplayChange(wParam, lParam);
case QtWindows::SettingChangedEvent: case QtWindows::SettingChangedEvent:
QWindowsWindow::settingsChanged();
return d->m_screenManager.handleScreenChanges(); return d->m_screenManager.handleScreenChanges();
default: default:
break; break;

View File

@ -1350,11 +1350,11 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
// Set the swap interval // Set the swap interval
if (m_staticContext->wglSwapInternalExt) { if (m_staticContext->wglSwapInternalExt) {
const int interval = surface->format().swapInterval(); const int interval = surface->format().swapInterval();
if (interval >= 0 && m_swapInterval != interval) { if (m_swapInterval != interval)
m_swapInterval = interval; m_swapInterval = interval;
if (interval >= 0)
m_staticContext->wglSwapInternalExt(interval); m_staticContext->wglSwapInternalExt(interval);
} }
}
return success; return success;
} }

View File

@ -54,7 +54,6 @@
# include "qwindowsdrag.h" # include "qwindowsdrag.h"
#endif #endif
#include <qpa/qwindowsysteminterface.h>
#include <QtGui/qguiapplication.h> #include <QtGui/qguiapplication.h>
#include <QtGui/qscreen.h> #include <QtGui/qscreen.h>
#include <QtGui/qtouchdevice.h> #include <QtGui/qtouchdevice.h>
@ -201,6 +200,8 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
return false; return false;
} }
m_lastPointerType = pointerType;
// Handle non-client pen/touch as generic mouse events for compatibility with QDockWindow. // Handle non-client pen/touch as generic mouse events for compatibility with QDockWindow.
if ((pointerType == QT_PT_TOUCH || pointerType == QT_PT_PEN) && (et & QtWindows::NonClientEventFlag)) { if ((pointerType == QT_PT_TOUCH || pointerType == QT_PT_PEN) && (et & QtWindows::NonClientEventFlag)) {
POINTER_INFO pointerInfo; POINTER_INFO pointerInfo;
@ -427,6 +428,15 @@ static bool isValidWheelReceiver(QWindow *candidate)
return false; return false;
} }
static bool isMenuWindow(QWindow *window)
{
if (window)
if (QObject *fo = window->focusObject())
if (fo->inherits("QMenu"))
return true;
return false;
}
static QTouchDevice *createTouchDevice() static QTouchDevice *createTouchDevice()
{ {
const int digitizers = GetSystemMetrics(SM_DIGITIZER); const int digitizers = GetSystemMetrics(SM_DIGITIZER);
@ -455,6 +465,103 @@ QTouchDevice *QWindowsPointerHandler::ensureTouchDevice()
return m_touchDevice; return m_touchDevice;
} }
void QWindowsPointerHandler::handleCaptureRelease(QWindow *window,
QWindow *currentWindowUnderPointer,
HWND hwnd,
QEvent::Type eventType,
Qt::MouseButtons mouseButtons)
{
QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
// Qt expects the platform plugin to capture the mouse on any button press until release.
if (!platformWindow->hasMouseCapture() && eventType == QEvent::MouseButtonPress) {
platformWindow->setMouseGrabEnabled(true);
platformWindow->setFlag(QWindowsWindow::AutoMouseCapture);
qCDebug(lcQpaEvents) << "Automatic mouse capture " << window;
// Implement "Click to focus" for native child windows (unless it is a native widget window).
if (!window->isTopLevel() && !window->inherits("QWidgetWindow") && QGuiApplication::focusWindow() != window)
window->requestActivate();
} else if (platformWindow->hasMouseCapture()
&& platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)
&& eventType == QEvent::MouseButtonRelease
&& !mouseButtons) {
platformWindow->setMouseGrabEnabled(false);
qCDebug(lcQpaEvents) << "Releasing automatic mouse capture " << window;
}
// Enter new window: track to generate leave event.
// If there is an active capture, only track if the current window is capturing,
// so we don't get extra leave when cursor leaves the application.
if (window != m_currentWindow &&
(!platformWindow->hasMouseCapture() || currentWindowUnderPointer == window)) {
trackLeave(hwnd);
m_currentWindow = window;
}
}
void QWindowsPointerHandler::handleEnterLeave(QWindow *window,
QWindow *currentWindowUnderPointer,
QPoint globalPos)
{
QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
const bool hasCapture = platformWindow->hasMouseCapture();
// No enter or leave events are sent as long as there is an autocapturing window.
if (!hasCapture || !platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)) {
// Leave is needed if:
// 1) There is no capture and we move from a window to another window.
// Note: Leaving the application entirely is handled in translateMouseEvent(WM_MOUSELEAVE).
// 2) There is capture and we move out of the capturing window.
// 3) There is a new capture and we were over another window.
if ((m_windowUnderPointer && m_windowUnderPointer != currentWindowUnderPointer
&& (!hasCapture || window == m_windowUnderPointer))
|| (hasCapture && m_previousCaptureWindow != window && m_windowUnderPointer
&& m_windowUnderPointer != window)) {
qCDebug(lcQpaEvents) << "Leaving window " << m_windowUnderPointer;
QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer);
if (hasCapture && currentWindowUnderPointer != window) {
// Clear tracking if capturing and current window is not the capturing window
// to avoid leave when mouse actually leaves the application.
m_currentWindow = nullptr;
// We are not officially in any window, but we need to set some cursor to clear
// whatever cursor the left window had, so apply the cursor of the capture window.
platformWindow->applyCursor();
}
}
// Enter is needed if:
// 1) There is no capture and we move to a new window.
// 2) There is capture and we move into the capturing window.
// 3) The capture just ended and we are over non-capturing window.
if ((currentWindowUnderPointer && m_windowUnderPointer != currentWindowUnderPointer
&& (!hasCapture || currentWindowUnderPointer == window))
|| (m_previousCaptureWindow && !hasCapture && currentWindowUnderPointer
&& currentWindowUnderPointer != m_previousCaptureWindow)) {
QPoint wumLocalPos;
if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer)) {
wumLocalPos = wumPlatformWindow->mapFromGlobal(globalPos);
wumPlatformWindow->applyCursor();
}
qCDebug(lcQpaEvents) << "Entering window " << currentWindowUnderPointer;
QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, wumLocalPos, globalPos);
}
// We need to track m_windowUnderPointer separately from m_currentWindow, as Windows
// mouse tracking will not trigger WM_MOUSELEAVE for leaving window when mouse capture is set.
m_windowUnderPointer = currentWindowUnderPointer;
}
m_previousCaptureWindow = hasCapture ? window : nullptr;
}
bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND hwnd, bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND hwnd,
QtWindows::WindowsEventType et, QtWindows::WindowsEventType et,
MSG msg, PVOID vPointerInfo) MSG msg, PVOID vPointerInfo)
@ -464,9 +571,7 @@ bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND h
const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos); const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
const Qt::MouseButtons mouseButtons = mouseButtonsFromPointerFlags(pointerInfo->pointerFlags); const Qt::MouseButtons mouseButtons = mouseButtonsFromPointerFlags(pointerInfo->pointerFlags);
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
switch (msg.message) { switch (msg.message) {
case WM_NCPOINTERDOWN: case WM_NCPOINTERDOWN:
@ -485,38 +590,17 @@ bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND h
keyModifiers, Qt::MouseEventNotSynthesized); keyModifiers, Qt::MouseEventNotSynthesized);
return false; // To allow window dragging, etc. return false; // To allow window dragging, etc.
} else { } else {
if (eventType == QEvent::MouseButtonPress) {
// Implement "Click to focus" for native child windows (unless it is a native widget window).
if (!window->isTopLevel() && !window->inherits("QWidgetWindow") && QGuiApplication::focusWindow() != window)
window->requestActivate();
}
if (currentWindowUnderPointer != m_windowUnderPointer) {
if (m_windowUnderPointer && m_windowUnderPointer == m_currentWindow) {
QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer);
m_currentWindow = nullptr;
}
if (currentWindowUnderPointer) { handleCaptureRelease(window, currentWindowUnderPointer, hwnd, eventType, mouseButtons);
if (currentWindowUnderPointer != m_currentWindow) { handleEnterLeave(window, currentWindowUnderPointer, globalPos);
QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, localPos, globalPos);
m_currentWindow = currentWindowUnderPointer;
if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer))
wumPlatformWindow->applyCursor();
trackLeave(hwnd);
}
} else {
platformWindow->applyCursor();
}
m_windowUnderPointer = currentWindowUnderPointer;
}
QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType, QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType,
keyModifiers, Qt::MouseEventNotSynthesized); keyModifiers, Qt::MouseEventNotSynthesized);
// The initial down click over the QSizeGrip area, which posts a resize WM_SYSCOMMAND // The initial down click over the QSizeGrip area, which posts a resize WM_SYSCOMMAND
// has go to through DefWindowProc() for resizing to work, so we return false here, // has go to through DefWindowProc() for resizing to work, so we return false here,
// unless the mouse is captured, as it would mess with menu processing. // unless the click was on a menu, as it would mess with menu processing.
return msg.message != WM_POINTERDOWN || GetCapture(); return msg.message != WM_POINTERDOWN || isMenuWindow(window);
} }
} }
case WM_POINTERHWHEEL: case WM_POINTERHWHEEL:
@ -641,6 +725,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
// Only the primary pointer will generate mouse messages. // Only the primary pointer will generate mouse messages.
enqueueTouchEvent(window, touchPoints, QWindowsKeyMapper::queryKeyboardModifiers()); enqueueTouchEvent(window, touchPoints, QWindowsKeyMapper::queryKeyboardModifiers());
} else { } else {
flushTouchEvents(m_touchDevice);
QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints, QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints,
QWindowsKeyMapper::queryKeyboardModifiers()); QWindowsKeyMapper::queryKeyboardModifiers());
} }
@ -755,6 +840,16 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
#endif #endif
} }
static inline bool isMouseEventSynthesizedFromPenOrTouch()
{
// For details, see
// https://docs.microsoft.com/en-us/windows/desktop/tablet/system-events-and-mouse-messages
const LONG_PTR SIGNATURE_MASK = 0xFFFFFF00;
const LONG_PTR MI_WP_SIGNATURE = 0xFF515700;
return ((::GetMessageExtraInfo() & SIGNATURE_MASK) == MI_WP_SIGNATURE);
}
// Process old-style mouse messages here. // Process old-style mouse messages here.
bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result) bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
{ {
@ -763,8 +858,6 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW
flushTabletEvents(); flushTabletEvents();
*result = 0; *result = 0;
if (et != QtWindows::MouseWheelEvent && msg.message != WM_MOUSELEAVE && msg.message != WM_MOUSEMOVE)
return false;
const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam)); const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
QPoint localPos; QPoint localPos;
@ -778,7 +871,26 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW
} }
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle()); const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
// Handle "press and hold for right-clicking".
// We have to synthesize it here as it only comes from Windows as a fake RMB.
// MS docs say we could use bit 7 from extraInfo to distinguish pen from touch,
// but on the Surface it is set for both. So we use the last pointer type.
if (isMouseEventSynthesizedFromPenOrTouch()) {
if ((msg.message == WM_RBUTTONDOWN || msg.message == WM_RBUTTONUP)
&& (((m_lastPointerType == QT_PT_PEN)
&& QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents))
|| ((m_lastPointerType == QT_PT_TOUCH)
&& QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)))) {
QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, Qt::RightButton,
(msg.message == WM_RBUTTONDOWN) ? QEvent::MouseButtonPress
: QEvent::MouseButtonRelease,
keyModifiers, Qt::MouseEventSynthesizedBySystem);
}
// Messages synthesized from touch/pen are only used for flushing queues and press&hold.
return false;
}
if (et == QtWindows::MouseWheelEvent) { if (et == QtWindows::MouseWheelEvent) {
@ -799,50 +911,21 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW
} }
if (msg.message == WM_MOUSELEAVE) { if (msg.message == WM_MOUSELEAVE) {
if (window == m_currentWindow) { if (window == m_currentWindow) {
QWindowSystemInterface::handleLeaveEvent(window); QWindow *leaveTarget = m_windowUnderPointer ? m_windowUnderPointer : m_currentWindow;
qCDebug(lcQpaEvents) << "Leaving window " << leaveTarget;
QWindowSystemInterface::handleLeaveEvent(leaveTarget);
m_windowUnderPointer = nullptr; m_windowUnderPointer = nullptr;
m_currentWindow = nullptr; m_currentWindow = nullptr;
platformWindow->applyCursor();
}
return false;
} }
// Windows sends a mouse move with no buttons pressed to signal "Enter" } else if (msg.message == WM_MOUSEMOVE) {
// when a window is shown over the cursor. Discard the event and only use
// it for generating QEvent::Enter to be consistent with other platforms -
// X11 and macOS.
static QPoint lastMouseMovePos;
const bool discardEvent = msg.wParam == 0 && (m_windowUnderPointer.isNull() || globalPos == lastMouseMovePos);
lastMouseMovePos = globalPos;
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
handleCaptureRelease(window, currentWindowUnderPointer, hwnd, QEvent::MouseMove, mouseButtons);
if (currentWindowUnderPointer != m_windowUnderPointer) { handleEnterLeave(window, currentWindowUnderPointer, globalPos);
if (m_windowUnderPointer && m_windowUnderPointer == m_currentWindow) {
QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer);
m_currentWindow = nullptr;
} }
if (currentWindowUnderPointer) {
if (currentWindowUnderPointer != m_currentWindow) {
QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, localPos, globalPos);
m_currentWindow = currentWindowUnderPointer;
if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer))
wumPlatformWindow->applyCursor();
trackLeave(hwnd);
}
} else {
platformWindow->applyCursor();
}
m_windowUnderPointer = currentWindowUnderPointer;
}
const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
if (!discardEvent)
QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, Qt::NoButton, QEvent::MouseMove,
keyModifiers, Qt::MouseEventNotSynthesized);
return false; return false;
} }

View File

@ -46,6 +46,7 @@
#include <QtCore/qpointer.h> #include <QtCore/qpointer.h>
#include <QtCore/qscopedpointer.h> #include <QtCore/qscopedpointer.h>
#include <QtCore/qhash.h> #include <QtCore/qhash.h>
#include <qpa/qwindowsysteminterface.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -68,12 +69,16 @@ private:
bool translateMouseTouchPadEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPointerInfo); bool translateMouseTouchPadEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPointerInfo);
bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count); bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count);
bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo); bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo);
void handleCaptureRelease(QWindow *window, QWindow *currentWindowUnderPointer, HWND hwnd, QEvent::Type eventType, Qt::MouseButtons mouseButtons);
void handleEnterLeave(QWindow *window, QWindow *currentWindowUnderPointer, QPoint globalPos);
QTouchDevice *m_touchDevice = nullptr; QTouchDevice *m_touchDevice = nullptr;
QHash<int, QPointF> m_lastTouchPositions; QHash<int, QPointF> m_lastTouchPositions;
QPointer<QWindow> m_windowUnderPointer; QPointer<QWindow> m_windowUnderPointer;
QPointer<QWindow> m_currentWindow; QPointer<QWindow> m_currentWindow;
QWindow *m_previousCaptureWindow = nullptr;
bool m_needsEnterOnPointerUpdate = false; bool m_needsEnterOnPointerUpdate = false;
DWORD m_lastPointerType = 0;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -103,6 +103,13 @@ static void setIconContents(NOTIFYICONDATA &tnd, const QString &tip, HICON hIcon
qStringToLimitedWCharArray(tip, tnd.szTip, sizeof(tnd.szTip) / sizeof(wchar_t)); qStringToLimitedWCharArray(tip, tnd.szTip, sizeof(tnd.szTip) / sizeof(wchar_t));
} }
static void setIconVisibility(NOTIFYICONDATA &tnd, bool v)
{
tnd.uFlags |= NIF_STATE;
tnd.dwStateMask = NIS_HIDDEN;
tnd.dwState = v ? 0 : NIS_HIDDEN;
}
// Match the HWND of the dummy window to the instances // Match the HWND of the dummy window to the instances
struct QWindowsHwndSystemTrayIconEntry struct QWindowsHwndSystemTrayIconEntry
{ {
@ -176,12 +183,6 @@ static inline HWND createTrayIconMessageWindow()
QWindowsSystemTrayIcon::QWindowsSystemTrayIcon() QWindowsSystemTrayIcon::QWindowsSystemTrayIcon()
{ {
// For restoring the tray icon after explorer crashes
if (!MYWM_TASKBARCREATED)
MYWM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated");
// Allow the WM_TASKBARCREATED message through the UIPI filter
ChangeWindowMessageFilterEx(m_hwnd, MYWM_TASKBARCREATED, MSGFLT_ALLOW, 0);
qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this << "MYWM_TASKBARCREATED=" << MYWM_TASKBARCREATED;
} }
QWindowsSystemTrayIcon::~QWindowsSystemTrayIcon() QWindowsSystemTrayIcon::~QWindowsSystemTrayIcon()
@ -193,12 +194,15 @@ QWindowsSystemTrayIcon::~QWindowsSystemTrayIcon()
void QWindowsSystemTrayIcon::init() void QWindowsSystemTrayIcon::init()
{ {
qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this; qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this;
m_visible = true;
if (!setIconVisible(m_visible))
ensureInstalled(); ensureInstalled();
} }
void QWindowsSystemTrayIcon::cleanup() void QWindowsSystemTrayIcon::cleanup()
{ {
qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this; qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this;
m_visible = false;
ensureCleanup(); ensureCleanup();
} }
@ -310,6 +314,13 @@ bool QWindowsSystemTrayIcon::ensureInstalled()
m_hwnd = createTrayIconMessageWindow(); m_hwnd = createTrayIconMessageWindow();
if (Q_UNLIKELY(m_hwnd == nullptr)) if (Q_UNLIKELY(m_hwnd == nullptr))
return false; return false;
// For restoring the tray icon after explorer crashes
if (!MYWM_TASKBARCREATED)
MYWM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated");
// Allow the WM_TASKBARCREATED message through the UIPI filter
ChangeWindowMessageFilterEx(m_hwnd, MYWM_TASKBARCREATED, MSGFLT_ALLOW, nullptr);
qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this << "MYWM_TASKBARCREATED=" << MYWM_TASKBARCREATED;
QWindowsHwndSystemTrayIconEntry entry{m_hwnd, this}; QWindowsHwndSystemTrayIconEntry entry{m_hwnd, this};
hwndTrayIconEntries()->append(entry); hwndTrayIconEntries()->append(entry);
sendTrayMessage(NIM_ADD); sendTrayMessage(NIM_ADD);
@ -333,6 +344,18 @@ void QWindowsSystemTrayIcon::ensureCleanup()
m_toolTip.clear(); m_toolTip.clear();
} }
bool QWindowsSystemTrayIcon::setIconVisible(bool visible)
{
if (!isInstalled())
return false;
NOTIFYICONDATA tnd;
initNotifyIconData(tnd);
tnd.uID = q_uNOTIFYICONID;
tnd.hWnd = m_hwnd;
setIconVisibility(tnd, visible);
return Shell_NotifyIcon(NIM_MODIFY, &tnd) == TRUE;
}
bool QWindowsSystemTrayIcon::sendTrayMessage(DWORD msg) bool QWindowsSystemTrayIcon::sendTrayMessage(DWORD msg)
{ {
NOTIFYICONDATA tnd; NOTIFYICONDATA tnd;
@ -340,6 +363,8 @@ bool QWindowsSystemTrayIcon::sendTrayMessage(DWORD msg)
tnd.uID = q_uNOTIFYICONID; tnd.uID = q_uNOTIFYICONID;
tnd.hWnd = m_hwnd; tnd.hWnd = m_hwnd;
tnd.uFlags = NIF_SHOWTIP; tnd.uFlags = NIF_SHOWTIP;
if (msg != NIM_DELETE && !m_visible)
setIconVisibility(tnd, m_visible);
if (msg == NIM_ADD || msg == NIM_MODIFY) if (msg == NIM_ADD || msg == NIM_MODIFY)
setIconContents(tnd, m_toolTip, m_hIcon); setIconContents(tnd, m_toolTip, m_hIcon);
if (!Shell_NotifyIcon(msg, &tnd)) if (!Shell_NotifyIcon(msg, &tnd))

View File

@ -84,6 +84,7 @@ private:
bool ensureInstalled(); bool ensureInstalled();
void ensureCleanup(); void ensureCleanup();
bool sendTrayMessage(DWORD msg); bool sendTrayMessage(DWORD msg);
bool setIconVisible(bool visible);
HICON createIcon(const QIcon &icon); HICON createIcon(const QIcon &icon);
QIcon m_icon; QIcon m_icon;
@ -92,6 +93,7 @@ private:
HICON m_hIcon = nullptr; HICON m_hIcon = nullptr;
mutable QPointer<QWindowsPopupMenu> m_menu; mutable QPointer<QWindowsPopupMenu> m_menu;
bool m_ignoreNextMouseRelease = false; bool m_ignoreNextMouseRelease = false;
bool m_visible = false;
}; };
#ifndef QT_NO_DEBUG_STREAM #ifndef QT_NO_DEBUG_STREAM

View File

@ -482,26 +482,22 @@ struct WindowCreationData
typedef QWindowsWindowData WindowData; typedef QWindowsWindowData WindowData;
enum Flags { ForceChild = 0x1, ForceTopLevel = 0x2 }; enum Flags { ForceChild = 0x1, ForceTopLevel = 0x2 };
WindowCreationData() : parentHandle(0), type(Qt::Widget), style(0), exStyle(0),
topLevel(false), popup(false), dialog(false),
tool(false), embedded(false), hasAlpha(false) {}
void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0); void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0);
inline WindowData create(const QWindow *w, const WindowData &data, QString title) const; inline WindowData create(const QWindow *w, const WindowData &data, QString title) const;
inline void applyWindowFlags(HWND hwnd) const; inline void applyWindowFlags(HWND hwnd) const;
void initialize(const QWindow *w, HWND h, bool frameChange, qreal opacityLevel) const; void initialize(const QWindow *w, HWND h, bool frameChange, qreal opacityLevel) const;
Qt::WindowFlags flags; Qt::WindowFlags flags;
HWND parentHandle; HWND parentHandle = nullptr;
Qt::WindowType type; Qt::WindowType type = Qt::Widget;
unsigned style; unsigned style = 0;
unsigned exStyle; unsigned exStyle = 0;
bool topLevel; bool topLevel = false;
bool popup; bool popup = false;
bool dialog; bool dialog = false;
bool tool; bool tool = false;
bool embedded; bool embedded = false;
bool hasAlpha; bool hasAlpha = false;
}; };
QDebug operator<<(QDebug debug, const WindowCreationData &d) QDebug operator<<(QDebug debug, const WindowCreationData &d)
@ -555,12 +551,6 @@ static QScreen *screenForName(const QWindow *w, const QString &name)
return winScreen; return winScreen;
} }
static QScreen *forcedScreenForGLWindow(const QWindow *w)
{
const QString forceToScreen = GpuDescription::detect().gpuSuitableScreen;
return forceToScreen.isEmpty() ? nullptr : screenForName(w, forceToScreen);
}
static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &context, const QMargins &invMargins) static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &context, const QMargins &invMargins)
{ {
const QPoint orgPos(context->frameX - invMargins.left(), context->frameY - invMargins.top()); const QPoint orgPos(context->frameX - invMargins.left(), context->frameY - invMargins.top());
@ -569,7 +559,7 @@ static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &co
return orgPos; return orgPos;
// Workaround for QTBUG-50371 // Workaround for QTBUG-50371
const QScreen *screenForGL = forcedScreenForGLWindow(w); const QScreen *screenForGL = QWindowsWindow::forcedScreenForGLWindow(w);
if (!screenForGL) if (!screenForGL)
return orgPos; return orgPos;
@ -1364,6 +1354,28 @@ void QWindowsWindow::setDropSiteEnabled(bool dropEnabled)
#endif // QT_CONFIG(clipboard) && QT_CONFIG(draganddrop) #endif // QT_CONFIG(clipboard) && QT_CONFIG(draganddrop)
} }
bool QWindowsWindow::m_screenForGLInitialized = false;
void QWindowsWindow::displayChanged()
{
m_screenForGLInitialized = false;
}
void QWindowsWindow::settingsChanged()
{
m_screenForGLInitialized = false;
}
QScreen *QWindowsWindow::forcedScreenForGLWindow(const QWindow *w)
{
static QString forceToScreen;
if (!m_screenForGLInitialized) {
forceToScreen = GpuDescription::detect().gpuSuitableScreen;
m_screenForGLInitialized = true;
}
return forceToScreen.isEmpty() ? nullptr : screenForName(w, forceToScreen);
}
// Returns topmost QWindowsWindow ancestor even if there are embedded windows in the chain. // Returns topmost QWindowsWindow ancestor even if there are embedded windows in the chain.
// Returns this window if it is the topmost ancestor. // Returns this window if it is the topmost ancestor.
QWindow *QWindowsWindow::topLevelOf(QWindow *w) QWindow *QWindowsWindow::topLevelOf(QWindow *w)

View File

@ -297,6 +297,9 @@ public:
void handleHidden(); void handleHidden();
void handleCompositionSettingsChanged(); void handleCompositionSettingsChanged();
static void displayChanged();
static void settingsChanged();
static QScreen *forcedScreenForGLWindow(const QWindow *w);
static QWindowsWindow *windowsWindowOf(const QWindow *w); static QWindowsWindow *windowsWindowOf(const QWindow *w);
static QWindow *topLevelOf(QWindow *w); static QWindow *topLevelOf(QWindow *w);
static inline void *userDataOf(HWND hwnd); static inline void *userDataOf(HWND hwnd);
@ -378,6 +381,8 @@ private:
HICON m_iconBig = 0; HICON m_iconBig = 0;
void *m_surface = nullptr; void *m_surface = nullptr;
static bool m_screenForGLInitialized;
#if QT_CONFIG(vulkan) #if QT_CONFIG(vulkan)
// note: intentionally not using void * in order to avoid breaking x86 // note: intentionally not using void * in order to avoid breaking x86
VkSurfaceKHR m_vkSurface = 0; VkSurfaceKHR m_vkSurface = 0;

View File

@ -810,8 +810,9 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, i
connection()->flush(); connection()->flush();
// sleep 50 ms, so we don't use up CPU cycles all the time. const auto elapsed = timer.elapsed();
QThread::msleep(50); if (elapsed < clipboard_timeout)
queue->waitForNewEvents(clipboard_timeout - elapsed);
} while (timer.elapsed() < clipboard_timeout); } while (timer.elapsed() < clipboard_timeout);
return nullptr; return nullptr;

View File

@ -287,7 +287,7 @@ void QXcbBasicConnection::initializeShm()
logging->setEnabled(QtMsgType::QtWarningMsg, true); logging->setEnabled(QtMsgType::QtWarningMsg, true);
} }
void QXcbBasicConnection::initializeXRandr() void QXcbBasicConnection::initializeXRender()
{ {
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_render_id); const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_render_id);
if (!reply || !reply->present) { if (!reply || !reply->present) {
@ -303,7 +303,7 @@ void QXcbBasicConnection::initializeXRandr()
return; return;
} }
m_hasXRandr = true; m_hasXRender = true;
m_xrenderVersion.first = xrenderQuery->major_version; m_xrenderVersion.first = xrenderQuery->major_version;
m_xrenderVersion.second = xrenderQuery->minor_version; m_xrenderVersion.second = xrenderQuery->minor_version;
} }
@ -337,7 +337,7 @@ void QXcbBasicConnection::initializeXFixes()
m_xfixesFirstEvent = reply->first_event; m_xfixesFirstEvent = reply->first_event;
} }
void QXcbBasicConnection::initializeXRender() void QXcbBasicConnection::initializeXRandr()
{ {
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_randr_id); const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_randr_id);
if (!reply || !reply->present) if (!reply || !reply->present)
@ -352,7 +352,7 @@ void QXcbBasicConnection::initializeXRender()
return; return;
} }
m_hasXRender = true; m_hasXRandr = true;
m_xrandrFirstEvent = reply->first_event; m_xrandrFirstEvent = reply->first_event;
} }

View File

@ -229,6 +229,8 @@ void QXcbEventQueue::run()
enqueueEvent(event); enqueueEvent(event);
while (!m_closeConnectionDetected && (event = xcb_poll_for_queued_event(connection))) while (!m_closeConnectionDetected && (event = xcb_poll_for_queued_event(connection)))
enqueueEvent(event); enqueueEvent(event);
m_newEventsCondition.wakeOne();
wakeUpDispatcher(); wakeUpDispatcher();
} }
@ -346,6 +348,13 @@ bool QXcbEventQueue::peekEventQueue(PeekerCallback peeker, void *peekerData,
return result; return result;
} }
void QXcbEventQueue::waitForNewEvents(unsigned long time)
{
m_newEventsMutex.lock();
m_newEventsCondition.wait(&m_newEventsMutex, time);
m_newEventsMutex.unlock();
}
void QXcbEventQueue::sendCloseConnectionEvent() const void QXcbEventQueue::sendCloseConnectionEvent() const
{ {
// A hack to close XCB connection. Apparently XCB does not have any APIs for this? // A hack to close XCB connection. Apparently XCB does not have any APIs for this?

View File

@ -43,6 +43,8 @@
#include <QtCore/QHash> #include <QtCore/QHash>
#include <QtCore/QEventLoop> #include <QtCore/QEventLoop>
#include <QtCore/QVector> #include <QtCore/QVector>
#include <QtCore/QMutex>
#include <QtCore/QWaitCondition>
#include <xcb/xcb.h> #include <xcb/xcb.h>
@ -104,6 +106,8 @@ public:
bool peekEventQueue(PeekerCallback peeker, void *peekerData = nullptr, bool peekEventQueue(PeekerCallback peeker, void *peekerData = nullptr,
PeekOptions option = PeekDefault, qint32 peekerId = -1); PeekOptions option = PeekDefault, qint32 peekerId = -1);
void waitForNewEvents(unsigned long time = ULONG_MAX);
private: private:
QXcbEventNode *qXcbEventNodeFactory(xcb_generic_event_t *event); QXcbEventNode *qXcbEventNodeFactory(xcb_generic_event_t *event);
void dequeueNode(); void dequeueNode();
@ -131,6 +135,9 @@ private:
// debug stats // debug stats
quint64 m_nodesOnHeap = 0; quint64 m_nodesOnHeap = 0;
QMutex m_newEventsMutex;
QWaitCondition m_newEventsCondition;
}; };
template<typename Peeker> template<typename Peeker>

View File

@ -112,4 +112,8 @@ qtConfig(xkb) {
qtConfig(dlopen): QMAKE_USE += libdl qtConfig(dlopen): QMAKE_USE += libdl
# qxcbkeyboard.cpp's KeyTbl has more than 256 levels of expansion and older
# Clang uses that as a limit (it's 1024 in current versions).
clang:!intel_icc: QMAKE_CXXFLAGS += -ftemplate-depth=1024
load(qt_module) load(qt_module)

View File

@ -3217,6 +3217,29 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
static_cast<NSTextFieldCell *>(tf.cell).bezelStyle = isRounded ? NSTextFieldRoundedBezel : NSTextFieldSquareBezel; static_cast<NSTextFieldCell *>(tf.cell).bezelStyle = isRounded ? NSTextFieldRoundedBezel : NSTextFieldSquareBezel;
tf.frame = opt->rect.toCGRect(); tf.frame = opt->rect.toCGRect();
d->drawNSViewInRect(tf, opt->rect, p, ^(CGContextRef, const CGRect &rect) { d->drawNSViewInRect(tf, opt->rect, p, ^(CGContextRef, const CGRect &rect) {
if (!qt_mac_applicationIsInDarkMode()) {
// In 'Dark' mode controls are transparent, so we do not
// over-paint the (potentially custom) color in the background.
// In 'Light' mode we have to care about the correct
// background color. See the comments below for PE_PanelLineEdit.
CGContextRef cgContext = NSGraphicsContext.currentContext.CGContext;
// See QMacCGContext, here we expect bitmap context created with
// color space 'kCGColorSpaceSRGB', if it's something else - we
// give up.
if (cgContext ? bool(CGBitmapContextGetColorSpace(cgContext)) : false) {
tf.drawsBackground = YES;
const QColor bgColor = frame->palette.brush(QPalette::Base).color();
tf.backgroundColor = [NSColor colorWithSRGBRed:bgColor.redF()
green:bgColor.greenF()
blue:bgColor.blueF()
alpha:bgColor.alphaF()];
if (bgColor.alpha() != 255) {
// No way we can have it bezeled and transparent ...
tf.bordered = YES;
}
}
}
[tf.cell drawWithFrame:rect inView:tf]; [tf.cell drawWithFrame:rect inView:tf];
}); });
} else { } else {
@ -3225,10 +3248,25 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
} }
break; break;
case PE_PanelLineEdit: case PE_PanelLineEdit:
{
const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(opt);
if (qt_mac_applicationIsInDarkMode() || (panel && panel->lineWidth <= 0)) {
// QCommonStyle::drawPrimitive(PE_PanelLineEdit) fill the background with
// a proper color, defined in opt->palette and then, if lineWidth > 0, it
// calls QMacStyle::drawPrimitive(PE_FrameLineEdit). We use NSTextFieldCell
// to handle PE_FrameLineEdit, which will use system-default background.
// In 'Dark' mode it's transparent and thus it's not over-painted.
QCommonStyle::drawPrimitive(pe, opt, p, w); QCommonStyle::drawPrimitive(pe, opt, p, w);
} else {
// In 'Light' mode, if panel->lineWidth > 0, we have to use the correct
// background color when drawing PE_FrameLineEdit, so let's call it
// directly and set the proper color there.
drawPrimitive(PE_FrameLineEdit, opt, p, w);
}
// Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit). // Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit).
// Focus frame is drawn outside the rectangle passed in the option-rect. // Focus frame is drawn outside the rectangle passed in the option-rect.
if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(opt)) { if (panel) {
#if QT_CONFIG(lineedit) #if QT_CONFIG(lineedit)
if ((opt->state & State_HasFocus) && !qobject_cast<const QLineEdit*>(w)) { if ((opt->state & State_HasFocus) && !qobject_cast<const QLineEdit*>(w)) {
int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin); int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin);
@ -3239,7 +3277,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
} }
#endif #endif
} }
}
break; break;
case PE_PanelScrollAreaCorner: { case PE_PanelScrollAreaCorner: {
const QBrush brush(opt->palette.brush(QPalette::Base)); const QBrush brush(opt->palette.brush(QPalette::Base));

View File

@ -3,9 +3,9 @@
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the documentation of the Qt Toolkit. ** This file is part of the QtGui module of the Qt Toolkit.
** **
** $QT_BEGIN_LICENSE:FDL$ ** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage ** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in ** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the ** accordance with the commercial license agreement provided with the
@ -14,13 +14,25 @@
** and conditions see https://www.qt.io/terms-conditions. For further ** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us. ** information use the contact form at https://www.qt.io/contact-us.
** **
** GNU Free Documentation License Usage ** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Free ** Alternatively, this file may be used under the terms of the GNU Lesser
** Documentation License version 1.3 as published by the Free Software ** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of ** Foundation and appearing in the file LICENSE.LGPL3 included in the
** this file. Please review the following information to ensure ** packaging of this file. Please review the following information to
** the GNU Free Documentation License version 1.3 requirements ** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$ ** $QT_END_LICENSE$
** **
****************************************************************************/ ****************************************************************************/

View File

@ -31,8 +31,16 @@ depends += qtcore qtdoc qtwidgets qtgui qmake qtqmltest
headerdirs += .. headerdirs += ..
headers += ../../corelib/kernel/qtestsupport_core.h \
../../gui/kernel/qtestsupport_gui.h \
../../widgets/kernel/qtestsupport_widgets.h
sourcedirs += .. sourcedirs += ..
sources += ../../corelib/kernel/qtestsupport_core.cpp \
../../gui/kernel/qtestsupport_gui.cpp \
../../widgets/kernel/qtestsupport_widgets.cpp
exampledirs += ../../../examples/qtestlib \ exampledirs += ../../../examples/qtestlib \
../ \ ../ \
snippets snippets

View File

@ -2426,7 +2426,7 @@ bool QTest::currentTestFailed()
Sleeps for \a ms milliseconds, blocking execution of the Sleeps for \a ms milliseconds, blocking execution of the
test. qSleep() will not do any event processing and leave your test test. qSleep() will not do any event processing and leave your test
unresponsive. Network communication might time out while unresponsive. Network communication might time out while
sleeping. Use \l qWait() to do non-blocking sleeping. sleeping. Use \l {QTest::qWait()} to do non-blocking sleeping.
\a ms must be greater than 0. \a ms must be greater than 0.
@ -2437,7 +2437,7 @@ bool QTest::currentTestFailed()
Example: Example:
\snippet code/src_qtestlib_qtestcase.cpp 23 \snippet code/src_qtestlib_qtestcase.cpp 23
\sa qWait() \sa {QTest::qWait()}
*/ */
void QTest::qSleep(int ms) void QTest::qSleep(int ms)
{ {

View File

@ -994,6 +994,22 @@
\sa QTest::toHexRepresentation() \sa QTest::toHexRepresentation()
*/ */
/*!
\fn char *QTest::toString(const QCborError &c)
\overload
\since 5.12
Returns a textual representation of the given CBOR error \a c.
*/
/*!
\fn template <class... Types> char *QTest::toString(const std::tuple<Types...> &tuple)
\overload
\since 5.12
Returns a textual representation of the given \a tuple.
*/
/*! /*!
\fn char *QTest::toString(const QTime &time) \fn char *QTest::toString(const QTime &time)
\overload \overload
@ -1112,6 +1128,12 @@
Returns a textual representation of size policy \a sp. Returns a textual representation of size policy \a sp.
*/ */
/*!
\fn template <typename Tuple, int... I> char *QTest::toString(const Tuple &tuple, QtPrivate::IndexesList<I...> )
\internal
\since 5.12
*/
/*! /*!
\fn QTouchDevice *QTest::createTouchDevice(QTouchDevice::DeviceType devType = QTouchDevice::TouchScreen) \fn QTouchDevice *QTest::createTouchDevice(QTouchDevice::DeviceType devType = QTouchDevice::TouchScreen)
\since 5.8 \since 5.8

View File

@ -133,7 +133,7 @@
Adds a \a msecs milliseconds delay. Adds a \a msecs milliseconds delay.
\sa QTest::qWait() \sa {QTest::qWait()}
*/ */
/*! \fn void QTestEventList::simulate(QWidget *w) /*! \fn void QTestEventList::simulate(QWidget *w)

View File

@ -136,8 +136,9 @@ void QXmlTestLogger::startLogging()
void QXmlTestLogger::stopLogging() void QXmlTestLogger::stopLogging()
{ {
QTestCharBuffer buf; QTestCharBuffer buf;
QTest::qt_asprintf(&buf,
"<Duration msecs=\"%f\"/>\n", QTestLog::msecsTotalTime()); QTest::qt_asprintf(&buf, "<Duration msecs=\"%s\"/>\n",
QString::number(QTestLog::msecsTotalTime()).toUtf8().constData());
outputString(buf.constData()); outputString(buf.constData());
if (xmlmode == QXmlTestLogger::Complete) { if (xmlmode == QXmlTestLogger::Complete) {
outputString("</TestCase>\n"); outputString("</TestCase>\n");
@ -159,9 +160,9 @@ void QXmlTestLogger::leaveTestFunction()
{ {
QTestCharBuffer buf; QTestCharBuffer buf;
QTest::qt_asprintf(&buf, QTest::qt_asprintf(&buf,
" <Duration msecs=\"%f\"/>\n" " <Duration msecs=\"%s\"/>\n"
"</TestFunction>\n", "</TestFunction>\n",
QTestLog::msecsFunctionTime()); QString::number(QTestLog::msecsFunctionTime()).toUtf8().constData());
outputString(buf.constData()); outputString(buf.constData());
} }

View File

@ -62,7 +62,7 @@ static const char docTypeHeader[] =
#define PROGRAMNAME "qdbuscpp2xml" #define PROGRAMNAME "qdbuscpp2xml"
#define PROGRAMVERSION "0.2" #define PROGRAMVERSION "0.2"
#define PROGRAMCOPYRIGHT "Copyright (C) 2018 The Qt Company Ltd." #define PROGRAMCOPYRIGHT "Copyright (C) 2019 The Qt Company Ltd."
static QString outputFile; static QString outputFile;
static int flags; static int flags;

View File

@ -46,7 +46,7 @@
#define PROGRAMNAME "qdbusxml2cpp" #define PROGRAMNAME "qdbusxml2cpp"
#define PROGRAMVERSION "0.8" #define PROGRAMVERSION "0.8"
#define PROGRAMCOPYRIGHT "Copyright (C) 2018 The Qt Company Ltd." #define PROGRAMCOPYRIGHT "Copyright (C) 2019 The Qt Company Ltd."
#define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply" #define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply"

View File

@ -1890,7 +1890,7 @@ void QMessageBox::aboutQt(QWidget *parent, const QString &title)
"<p>Qt and the Qt logo are trademarks of The Qt Company Ltd.</p>" "<p>Qt and the Qt logo are trademarks of The Qt Company Ltd.</p>"
"<p>Qt is The Qt Company Ltd product developed as an open source " "<p>Qt is The Qt Company Ltd product developed as an open source "
"project. See <a href=\"http://%3/\">%3</a> for more information.</p>" "project. See <a href=\"http://%3/\">%3</a> for more information.</p>"
).arg(QStringLiteral("2018"), ).arg(QStringLiteral("2019"),
QStringLiteral("qt.io/licensing"), QStringLiteral("qt.io/licensing"),
QStringLiteral("qt.io")); QStringLiteral("qt.io"));
QMessageBox *msgBox = new QMessageBox(parent); QMessageBox *msgBox = new QMessageBox(parent);

View File

@ -40,6 +40,9 @@ exampledirs += ../../../examples/widgets \
excludedirs += snippets excludedirs += snippets
# Included in qttestlib.qdocconf instead
excludefiles += ../kernel/qtestsupport_widgets.cpp
imagedirs += images \ imagedirs += images \
../../../doc/src/images \ ../../../doc/src/images \
../../../examples/widgets/doc/images \ ../../../examples/widgets/doc/images \

View File

@ -982,18 +982,9 @@ void QListView::paintEvent(QPaintEvent *e)
? qMax(viewport()->size().width(), d->contentsSize().width()) - 2 * d->spacing() ? qMax(viewport()->size().width(), d->contentsSize().width()) - 2 * d->spacing()
: qMax(viewport()->size().height(), d->contentsSize().height()) - 2 * d->spacing(); : qMax(viewport()->size().height(), d->contentsSize().height()) - 2 * d->spacing();
const int rowCount = d->commonListView->rowCount();
QVector<QModelIndex>::const_iterator end = toBeRendered.constEnd(); QVector<QModelIndex>::const_iterator end = toBeRendered.constEnd();
for (QVector<QModelIndex>::const_iterator it = toBeRendered.constBegin(); it != end; ++it) { for (QVector<QModelIndex>::const_iterator it = toBeRendered.constBegin(); it != end; ++it) {
Q_ASSERT((*it).isValid()); Q_ASSERT((*it).isValid());
if (rowCount == 1)
option.viewItemPosition = QStyleOptionViewItem::OnlyOne;
else if ((*it).row() == 0)
option.viewItemPosition = QStyleOptionViewItem::Beginning;
else if ((*it).row() == rowCount - 1)
option.viewItemPosition = QStyleOptionViewItem::End;
else
option.viewItemPosition = QStyleOptionViewItem::Middle;
option.rect = visualRect(*it); option.rect = visualRect(*it);
if (flow() == TopToBottom) if (flow() == TopToBottom)

View File

@ -46,15 +46,14 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
/*! \fn bool qWaitForWindowActive(QWidget *widget, int timeout) /*!
\relates QTest
\since 5.0 \since 5.0
Waits for \a timeout milliseconds or until the \a widget's window is active. Waits for \a timeout milliseconds or until the \a widget's window is active.
Returns \c true if \c widget's window is active within \a timeout milliseconds, otherwise returns \c false. Returns \c true if \c widget's window is active within \a timeout milliseconds, otherwise returns \c false.
\sa QTest::qWaitForWindowExposed(), QWidget::isActiveWindow() \sa qWaitForWindowExposed(), QWidget::isActiveWindow()
*/ */
Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowActive(QWidget *widget, int timeout) Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowActive(QWidget *widget, int timeout)
{ {
@ -63,8 +62,7 @@ Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowActive(QWidget *wid
return false; return false;
} }
/*! \fn bool qWaitForWindowExposed(QWidget *widget, int timeout) /*!
\relates QTest
\since 5.0 \since 5.0
Waits for \a timeout milliseconds or until the \a widget's window is exposed. Waits for \a timeout milliseconds or until the \a widget's window is exposed.
@ -80,7 +78,7 @@ Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowActive(QWidget *wid
A specific configuration where this happens is when using QGLWidget as a viewport widget on macOS: A specific configuration where this happens is when using QGLWidget as a viewport widget on macOS:
The viewport widget gets the expose event, not the parent widget. The viewport widget gets the expose event, not the parent widget.
\sa QTest::qWaitForWindowActive() \sa qWaitForWindowActive()
*/ */
Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowExposed(QWidget *widget, int timeout) Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowExposed(QWidget *widget, int timeout)
{ {
@ -89,11 +87,12 @@ Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowExposed(QWidget *wi
return false; return false;
} }
/*! \fn bool qWaitForWindowShown(QWidget *widget, int timeout) /*! \fn bool QTest::qWaitForWindowShown(QWidget *widget, int timeout)
\relates QTest
\since 5.0 \since 5.0
\deprecated \deprecated
Use qWaitForWindowExposed() instead.
Waits for \a timeout milliseconds or until the \a widget's window is exposed. Waits for \a timeout milliseconds or until the \a widget's window is exposed.
Returns \c true if \c widget's window is exposed within \a timeout milliseconds, otherwise returns \c false. Returns \c true if \c widget's window is exposed within \a timeout milliseconds, otherwise returns \c false.
@ -107,7 +106,7 @@ Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowExposed(QWidget *wi
QTest::qWaitForWindowShown(&widget); QTest::qWaitForWindowShown(&widget);
\endcode \endcode
\sa QTest::qWaitForWindowActive(), QTest::qWaitForWindowExposed() \sa qWaitForWindowActive(), qWaitForWindowExposed()
*/ */
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -216,7 +216,6 @@ void QTipLabel::reuseTip(const QString &text, int msecDisplayTime, const QPoint
} }
#endif #endif
setWordWrap(true);
setText(text); setText(text);
updateSize(pos); updateSize(pos);
restartExpireTimer(msecDisplayTime); restartExpireTimer(msecDisplayTime);
@ -235,20 +234,17 @@ void QTipLabel::updateSize(const QPoint &pos)
// Make it look good with the default ToolTip font on Mac, which has a small descent. // Make it look good with the default ToolTip font on Mac, which has a small descent.
if (fm.descent() == 2 && fm.ascent() >= 11) if (fm.descent() == 2 && fm.ascent() >= 11)
++extra.rheight(); ++extra.rheight();
setWordWrap(Qt::mightBeRichText(text()));
QSize sh = sizeHint(); QSize sh = sizeHint();
if (wordWrap()) {
// ### When the above WinRT code is fixed, windowhandle should be used to find the screen. // ### When the above WinRT code is fixed, windowhandle should be used to find the screen.
QScreen *screen = QGuiApplication::screenAt(pos); QScreen *screen = QGuiApplication::screenAt(pos);
if (!screen) if (!screen)
screen = QGuiApplication::primaryScreen(); screen = QGuiApplication::primaryScreen();
if (screen) { if (screen) {
const qreal screenWidth = screen->geometry().width(); const qreal screenWidth = screen->geometry().width();
if (sh.width() > screenWidth) { if (!wordWrap() && sh.width() > screenWidth) {
// Try to use widely accepted 75chars max length or 80% of the screen width else. setWordWrap(true);
// See https://en.wikipedia.org/wiki/Line_length sh = sizeHint();
sh.setWidth(qMin(fm.averageCharWidth() * 75, static_cast<int>(screenWidth * .8)));
sh.setHeight(heightForWidth(sh.width()));
}
} }
} }
resize(sh + extra); resize(sh + extra);

View File

@ -247,6 +247,7 @@ QWidgetPrivate::QWidgetPrivate(int version)
#ifndef QT_NO_TOOLTIP #ifndef QT_NO_TOOLTIP
, toolTipDuration(-1) , toolTipDuration(-1)
#endif #endif
, directFontResolveMask(0)
, inheritedFontResolveMask(0) , inheritedFontResolveMask(0)
, inheritedPaletteResolveMask(0) , inheritedPaletteResolveMask(0)
, leftmargin(0) , leftmargin(0)
@ -4519,7 +4520,7 @@ void QWidget::setForegroundRole(QPalette::ColorRole role)
the "color", "background-color", "selection-color", the "color", "background-color", "selection-color",
"selection-background-color" and "alternate-background-color". "selection-background-color" and "alternate-background-color".
\sa QApplication::palette(), QWidget::font(), \l {Qt Style Sheets} \sa QApplication::palette(), QWidget::font(), {Qt Style Sheets}
*/ */
const QPalette &QWidget::palette() const const QPalette &QWidget::palette() const
{ {
@ -4754,6 +4755,18 @@ QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
return naturalFont; return naturalFont;
} }
/*!
\internal
Returns a font suitable for inheritance, where only locally set attributes are considered resolved.
*/
QFont QWidgetPrivate::localFont() const
{
QFont localfont = data.fnt;
localfont.resolve(directFontResolveMask);
return localfont;
}
/*! /*!
\internal \internal
@ -4765,7 +4778,7 @@ QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const
void QWidgetPrivate::resolveFont() void QWidgetPrivate::resolveFont()
{ {
QFont naturalFont = naturalWidgetFont(inheritedFontResolveMask); QFont naturalFont = naturalWidgetFont(inheritedFontResolveMask);
QFont resolvedFont = data.fnt.resolve(naturalFont); QFont resolvedFont = localFont().resolve(naturalFont);
setFont_helper(resolvedFont); setFont_helper(resolvedFont);
} }
@ -4804,6 +4817,11 @@ void QWidgetPrivate::updateFont(const QFont &font)
inheritedFontResolveMask = 0; inheritedFontResolveMask = 0;
} }
uint newMask = data.fnt.resolve() | inheritedFontResolveMask; uint newMask = data.fnt.resolve() | inheritedFontResolveMask;
// Set the font as also having resolved inherited traits, so the result of reading QWidget::font()
// isn't all weak information, but save the original mask to be able to let new changes on the
// parent widget font propagate correctly.
directFontResolveMask = data.fnt.resolve();
data.fnt.resolve(newMask);
for (int i = 0; i < children.size(); ++i) { for (int i = 0; i < children.size(); ++i) {
QWidget *w = qobject_cast<QWidget*>(children.at(i)); QWidget *w = qobject_cast<QWidget*>(children.at(i));

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