From c3c5a58f654537059366ecd3fe9811716bc202d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 10 Feb 2020 21:55:55 +0100 Subject: [PATCH 01/28] macOS: Tag sub-layer images with color space on flush Failing to tag the image results in costly CPU-based color-space conversions. Change-Id: Ib65547f4b99b83e10d3603c27388f50eb4d3840c Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoabackingstore.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 2e15d115645..cb019c37753 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -574,7 +574,8 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion, qCInfo(lcQpaBackingStore) << "Flushing" << subImage << "to" << flushedView.layer << "of subview" << flushedView; - QCFType cgImage = subImage.toCGImage(); + QCFType cgImage = CGImageCreateCopyWithColorSpace( + QCFType(subImage.toCGImage()), colorSpace()); flushedView.layer.contents = (__bridge id)static_cast(cgImage); } From 8aef4fe9a4a6f069f27c185d57f461980d99a814 Mon Sep 17 00:00:00 2001 From: Paul Wicking Date: Thu, 6 Feb 2020 07:25:12 +0100 Subject: [PATCH 02/28] Doc: Fix documentation for QSortFilterProxyModel::filterAcceptsColumn filterAcceptsColumn always returns true unconditionally and must be reimplemented (overridden) by user code to achieve the described behavior. Change the documentation to reflect this fact. Fixes: QTBUG-81654 Change-Id: I0dade63294598238d2ad54ab251b4c1b27c72cdf Reviewed-by: Sze Howe Koh --- src/corelib/itemmodels/qsortfilterproxymodel.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index 21303549abe..61d37d5062a 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -3055,12 +3055,8 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex & Returns \c true if the item in the column indicated by the given \a source_column and \a source_parent should be included in the model; otherwise returns \c false. - The default implementation returns \c true if the value held by the relevant item - matches the filter string, wildcard string or regular expression. - - \note By default, the Qt::DisplayRole is used to determine if the column - should be accepted or not. This can be changed by setting the \l - filterRole property. + \note The default implementation always returns \c true. You must reimplement this + method to get the described behavior. \sa filterAcceptsRow(), setFilterFixedString(), setFilterRegExp(), setFilterWildcard() */ From 217b7d2dd64551ea499766b538551d31319c01cd Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 11 Feb 2020 12:30:46 +0100 Subject: [PATCH 03/28] Add \since to namespace QColorConstants Introduced by 77de5a329c98c3787725cb3c0a50d8f369b9479c. Change-Id: Ib99dd38c72a74f2ae9c0dfbcecf659fe75f9a27d Reviewed-by: Marc Mutz --- src/gui/painting/qcolor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index 8780cce2230..e75e42c007a 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -3264,6 +3264,7 @@ const uint qt_inv_premul_factor[256] = { /*! \namespace QColorConstants \inmodule QtGui + \since 5.14 \brief The QColorConstants namespace contains QColor predefined constants. From a82f9f1a1d7a9a0bd0ceebac6a2bc765b01877e5 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Fri, 13 Dec 2019 17:13:44 +0100 Subject: [PATCH 04/28] Windows QPA: Implement IExpandCollapseProvider for submenus Menu items with submenus should implement the Expand/Collapse UI Automation pattern in order to allow screen readers to say whether they are expandable items. Fixes: QTBUG-80550 Change-Id: I4f72d30172f76f028be5cbdeb1fd85fca6b07acf Reviewed-by: Friedemann Kleint Reviewed-by: Oliver Wolff --- .../uiaserverinterfaces_p.h | 17 +++ .../windowsuiautomation/uiatypes_p.h | 7 + .../qwindowsuiaexpandcollapseprovider.cpp | 120 ++++++++++++++++++ .../qwindowsuiaexpandcollapseprovider.h | 69 ++++++++++ .../uiautomation/qwindowsuiamainprovider.cpp | 9 ++ .../windows/uiautomation/uiautomation.pri | 2 + 6 files changed, 224 insertions(+) create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp create mode 100644 src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.h diff --git a/src/platformsupport/windowsuiautomation/uiaserverinterfaces_p.h b/src/platformsupport/windowsuiautomation/uiaserverinterfaces_p.h index fd39b6ee339..fde16206daa 100644 --- a/src/platformsupport/windowsuiautomation/uiaserverinterfaces_p.h +++ b/src/platformsupport/windowsuiautomation/uiaserverinterfaces_p.h @@ -383,4 +383,21 @@ __CRT_UUID_DECL(IWindowProvider, 0x987df77b, 0xdb06, 0x4d77, 0x8f,0x8a, 0x86,0xa #endif #endif + +#ifndef __IExpandCollapseProvider_INTERFACE_DEFINED__ +#define __IExpandCollapseProvider_INTERFACE_DEFINED__ +DEFINE_GUID(IID_IExpandCollapseProvider, 0xd847d3a5, 0xcab0, 0x4a98, 0x8c,0x32, 0xec,0xb4,0x5c,0x59,0xad,0x24); +MIDL_INTERFACE("d847d3a5-cab0-4a98-8c32-ecb45c59ad24") +IExpandCollapseProvider : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE Expand() = 0; + virtual HRESULT STDMETHODCALLTYPE Collapse() = 0; + virtual HRESULT STDMETHODCALLTYPE get_ExpandCollapseState(__RPC__out enum ExpandCollapseState *pRetVal) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IExpandCollapseProvider, 0xd847d3a5, 0xcab0, 0x4a98, 0x8c,0x32, 0xec,0xb4,0x5c,0x59,0xad,0x24) +#endif +#endif + #endif diff --git a/src/platformsupport/windowsuiautomation/uiatypes_p.h b/src/platformsupport/windowsuiautomation/uiatypes_p.h index 8ef71843a3e..afbc9570941 100644 --- a/src/platformsupport/windowsuiautomation/uiatypes_p.h +++ b/src/platformsupport/windowsuiautomation/uiatypes_p.h @@ -155,6 +155,13 @@ enum WindowInteractionState { WindowInteractionState_NotResponding = 4 }; +enum ExpandCollapseState { + ExpandCollapseState_Collapsed = 0, + ExpandCollapseState_Expanded = 1, + ExpandCollapseState_PartiallyExpanded = 2, + ExpandCollapseState_LeafNode = 3 +}; + struct UiaRect { double left; double top; diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp new file mode 100644 index 00000000000..6ac8de23fa0 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.cpp @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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$ +** +****************************************************************************/ + +#include +#if QT_CONFIG(accessibility) + +#include "qwindowsuiaexpandcollapseprovider.h" +#include "qwindowsuiautils.h" +#include "qwindowscontext.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QWindowsUiAutomation; + + +QWindowsUiaExpandCollapseProvider::QWindowsUiaExpandCollapseProvider(QAccessible::Id id) : + QWindowsUiaBaseProvider(id) +{ +} + +QWindowsUiaExpandCollapseProvider::~QWindowsUiaExpandCollapseProvider() = default; + +HRESULT STDMETHODCALLTYPE QWindowsUiaExpandCollapseProvider::Expand() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleActionInterface *actionInterface = accessible->actionInterface(); + if (!actionInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + if (accessible->childCount() > 0 && accessible->child(0)->state().invisible) + actionInterface->doAction(QAccessibleActionInterface::showMenuAction()); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaExpandCollapseProvider::Collapse() +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + QAccessibleActionInterface *actionInterface = accessible->actionInterface(); + if (!actionInterface) + return UIA_E_ELEMENTNOTAVAILABLE; + + if (accessible->childCount() > 0 && !accessible->child(0)->state().invisible) + actionInterface->doAction(QAccessibleActionInterface::showMenuAction()); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsUiaExpandCollapseProvider::get_ExpandCollapseState(__RPC__out ExpandCollapseState *pRetVal) +{ + qCDebug(lcQpaUiAutomation) << __FUNCTION__; + + if (!pRetVal) + return E_INVALIDARG; + *pRetVal = ExpandCollapseState_LeafNode; + + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return UIA_E_ELEMENTNOTAVAILABLE; + + if (accessible->childCount() > 0) + *pRetVal = accessible->child(0)->state().invisible ? + ExpandCollapseState_Collapsed : ExpandCollapseState_Expanded; + + return S_OK; +} + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.h new file mode 100644 index 00000000000..f5b4c2e78b4 --- /dev/null +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaexpandcollapseprovider.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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 QWINDOWSUIAEXPANDCOLLAPSEPROVIDER_H +#define QWINDOWSUIAEXPANDCOLLAPSEPROVIDER_H + +#include +#if QT_CONFIG(accessibility) + +#include "qwindowsuiabaseprovider.h" + +QT_BEGIN_NAMESPACE + +// Implements the Expand/Collapse control pattern provider. Used for menu items with submenus. +class QWindowsUiaExpandCollapseProvider : public QWindowsUiaBaseProvider, + public QWindowsComBase +{ + Q_DISABLE_COPY_MOVE(QWindowsUiaExpandCollapseProvider) +public: + explicit QWindowsUiaExpandCollapseProvider(QAccessible::Id id); + virtual ~QWindowsUiaExpandCollapseProvider() override; + + // IExpandCollapseProvider + HRESULT STDMETHODCALLTYPE Expand() override; + HRESULT STDMETHODCALLTYPE Collapse() override; + HRESULT STDMETHODCALLTYPE get_ExpandCollapseState(__RPC__out ExpandCollapseState *pRetVal) override; +}; + +QT_END_NAMESPACE + +#endif // QT_CONFIG(accessibility) + +#endif // QWINDOWSUIAEXPANDCOLLAPSEPROVIDER_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index cc293b777c4..c89dea3dfb7 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -53,6 +53,7 @@ #include "qwindowsuiagridprovider.h" #include "qwindowsuiagriditemprovider.h" #include "qwindowsuiawindowprovider.h" +#include "qwindowsuiaexpandcollapseprovider.h" #include "qwindowscombase.h" #include "qwindowscontext.h" #include "qwindowsuiautils.h" @@ -341,6 +342,14 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow *pRetVal = new QWindowsUiaInvokeProvider(id()); } break; + case UIA_ExpandCollapsePatternId: + // Menu items with submenus. + if (accessible->role() == QAccessible::MenuItem + && accessible->childCount() > 0 + && accessible->child(0)->role() == QAccessible::PopupMenu) { + *pRetVal = new QWindowsUiaExpandCollapseProvider(id()); + } + break; default: break; } diff --git a/src/plugins/platforms/windows/uiautomation/uiautomation.pri b/src/plugins/platforms/windows/uiautomation/uiautomation.pri index ee9332e7ea7..1c4b018d1c2 100644 --- a/src/plugins/platforms/windows/uiautomation/uiautomation.pri +++ b/src/plugins/platforms/windows/uiautomation/uiautomation.pri @@ -19,6 +19,7 @@ SOURCES += \ $$PWD/qwindowsuiagridprovider.cpp \ $$PWD/qwindowsuiagriditemprovider.cpp \ $$PWD/qwindowsuiawindowprovider.cpp \ + $$PWD/qwindowsuiaexpandcollapseprovider.cpp \ $$PWD/qwindowsuiautils.cpp HEADERS += \ @@ -39,6 +40,7 @@ HEADERS += \ $$PWD/qwindowsuiagridprovider.h \ $$PWD/qwindowsuiagriditemprovider.h \ $$PWD/qwindowsuiawindowprovider.h \ + $$PWD/qwindowsuiaexpandcollapseprovider.h \ $$PWD/qwindowsuiautils.h mingw: QMAKE_USE *= uuid From 5234c6c6a8b8ee7cc33dde41c37dd3866c99405b Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 7 Feb 2020 15:00:55 +0100 Subject: [PATCH 05/28] Account for a reply that is finished before we can connect the signals In a case where a connection is refused, then it is possible for it to fail at the time that the QHttpNetworkReply is being created and therefore after the connections have been made it would have already emitted the signal to indicate it was finished with an error. To account for this, then it checks if there is an error code set on the reply and if there is then it will call the relevant slot right away. Fixes: QTBUG-57799 Change-Id: I4e73e5c82092c09f825343d18db40b47c3cdb9ac Reviewed-by: Timur Pocheptsov --- src/network/access/qhttpnetworkconnectionchannel.cpp | 1 + src/network/access/qhttpnetworkreply.cpp | 5 +++++ src/network/access/qhttpnetworkreply_p.h | 3 +++ src/network/access/qhttpthreaddelegate.cpp | 6 ++++++ 4 files changed, 15 insertions(+) diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 39f392a79bf..e81f042bdc2 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -1099,6 +1099,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket if (reply) { reply->d_func()->errorString = errorString; + reply->d_func()->httpErrorCode = errorCode; emit reply->finishedWithError(errorCode, errorString); reply = 0; if (protocolHandler) diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index a8b635c45aa..7ccac88878b 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -158,6 +158,11 @@ QString QHttpNetworkReply::errorString() const return d_func()->errorString; } +QNetworkReply::NetworkError QHttpNetworkReply::errorCode() const +{ + return d_func()->httpErrorCode; +} + QString QHttpNetworkReply::reasonPhrase() const { return d_func()->reasonPhrase; diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 12cfe359aaf..9c03a403e17 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -115,6 +115,8 @@ public: QString errorString() const; void setErrorString(const QString &error); + QNetworkReply::NetworkError errorCode() const; + QString reasonPhrase() const; qint64 bytesAvailable() const; @@ -259,6 +261,7 @@ public: qint64 removedContentLength; QPointer connection; QPointer connectionChannel; + QNetworkReply::NetworkError httpErrorCode = QNetworkReply::NoError; bool autoDecompress; diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index 63a3c4f204a..de14260d692 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -428,6 +428,12 @@ void QHttpThreadDelegate::startRequest() connect(httpReply, SIGNAL(cacheCredentials(QHttpNetworkRequest,QAuthenticator*)), this, SLOT(cacheCredentialsSlot(QHttpNetworkRequest,QAuthenticator*))); + if (httpReply->errorCode() != QNetworkReply::NoError) { + if (synchronous) + synchronousFinishedWithErrorSlot(httpReply->errorCode(), httpReply->errorString()); + else + finishedWithErrorSlot(httpReply->errorCode(), httpReply->errorString()); + } } // This gets called from the user thread or by the synchronous HTTP timeout timer From 97bb1ddc0815997b27e831073085df277bd9e32e Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Tue, 11 Feb 2020 13:58:06 +0800 Subject: [PATCH 06/28] Doc: Document some missing CONFIG values Task-number: QTBUG-81035 Change-Id: I1976e700aa9cfcc32ad8cb1d4fae5b2d7497c429 Reviewed-by: Kai Koehne Reviewed-by: Leena Miettinen --- qmake/doc/src/qmake-manual.qdoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index 4c71ceb9293..1e1e23495c0 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -960,6 +960,10 @@ default is used. \row \li thread \li Thread support is enabled. This is enabled when CONFIG includes \c qt, which is the default. + \row \li utf8_source \li Specifies that the project's source files use the + UTF-8 encoding. By default, the compiler default is used. + \row \li hide_symbols \li Set the default visibility of symbols in the binary + to hidden. By default, the compiler default is used. \row \li c99 \li C99 support is enabled. This option has no effect if the compiler does not support C99, or can't select the C standard. By default, the compiler default is used. From 0091a50bbd1486b2ee1713ac2a63e4117f6ccd78 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 10 Feb 2020 10:14:54 +0100 Subject: [PATCH 07/28] Doc: Fix botched attempt of documenting the 'relocatable' feature We don't have a -relocatable configure switch. Move the documentation to the right place (configure -list-features). The correct configure switches to turn the feature on/off are -feature-relocatable and -no-feature-relocatable. Task-number: QTBUG-80928 Change-Id: I96df0f44f12b2efe5a64132e9006d4b73de41255 Reviewed-by: Alexandru Croitor Reviewed-by: Tasuku Suzuki Reviewed-by: Yuhang Zhao <2546789017@qq.com> --- config_help.txt | 2 -- configure.json | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/config_help.txt b/config_help.txt index 0231234cf92..15627a179b2 100644 --- a/config_help.txt +++ b/config_help.txt @@ -163,8 +163,6 @@ Build options: -reduce-exports ...... Reduce amount of exported symbols [auto] -reduce-relocations .. Reduce amount of relocations [auto] (Unix only) - -relocatable ......... Enable the Qt installation to be relocated [auto] - -plugin-manifests .... Embed manifests into plugins [no] (Windows only) -static-runtime ...... With -static, use static runtime [no] (Windows only) diff --git a/configure.json b/configure.json index 62d78f8dc6b..868f15db134 100644 --- a/configure.json +++ b/configure.json @@ -1380,6 +1380,7 @@ }, "relocatable": { "label": "Relocatable", + "purpose": "Enable the Qt installation to be relocated.", "autoDetect": "features.shared", "condition": "features.dlopen || config.win32 || !features.shared", "output": [ "privateFeature" ] From 2310d9dc65b4d69e04e4aaa4f393722b7fff653d Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Wed, 15 Jan 2020 12:56:15 +0100 Subject: [PATCH 08/28] qmake: Allow the use of a response file when building a library Change b274f656b82e06fad492e241dae6ae65cb377ad1 enabled the use of a response file for application building specifically needed when building an application for Android on Windows. The same cause can happen when building a library too with a lot of object files, so the command for the link step can be too long. So we expand the functionality to be used for libraries too. Task-number: QTBUG-71940 Change-Id: Ia6d1943bf33f6decb53f6e71a8dc65310d2f20a1 Reviewed-by: Joerg Bornemann --- qmake/generators/unix/unixmake2.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 550fa9d834c..91470fb129b 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -558,6 +558,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << destdir_d << depVar("TARGET") << ": " << depVar("PRE_TARGETDEPS") << ' ' << incr_deps << " $(SUBLIBS) " << target_deps << ' ' << depVar("POST_TARGETDEPS"); } else { + ProStringList &cmd = project->values("QMAKE_LINK_SHLIB_CMD"); + cmd[0] = cmd.at(0).toQString().replace(QLatin1String("$(OBJECTS)"), objectParts.second); t << destdir_d << depVar("TARGET") << ": " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) $(SUBLIBS) $(OBJCOMP) " << target_deps << ' ' << depVar("POST_TARGETDEPS"); From 5ff37f13ee577c006f0b99307d0afa1cf991db08 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 7 Feb 2020 12:21:33 -0800 Subject: [PATCH 09/28] QTcpSocket::bind: fix issue found by BLACKLIST The comment in QNativeSocketEnginePrivate::fetchConnectionParameters() talked about IPv6 v4-mapped addresses. However, toIPv4Address also converts the unspecified address (::), which resulted in QAbstractSocket saying that it had bound to QHostAddress::Any instead of QHostAddress::AnyV6 Change-Id: I572733186b73423b89e5fffd15f138579c5c0c50 Reviewed-by: Timur Pocheptsov --- src/network/socket/qnativesocketengine_win.cpp | 3 ++- tests/auto/network/socket/qtcpsocket/BLACKLIST | 7 ------- tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp | 2 +- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 9edabd7822f..78be0a7e0f4 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -588,7 +588,8 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() // local address of the socket which bound on both IPv4 and IPv6 interfaces. // This address does not match to any special address and should not be used // to send the data. So, replace it with QHostAddress::Any. - if (socketProtocol == QAbstractSocket::IPv6Protocol) { + const uchar ipv6MappedNet[] = {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0}; + if (localAddress.isInSubnet(QHostAddress(ipv6MappedNet), 128 - 32)) { bool ok = false; const quint32 localIPv4 = localAddress.toIPv4Address(&ok); if (ok && localIPv4 == INADDR_ANY) { diff --git a/tests/auto/network/socket/qtcpsocket/BLACKLIST b/tests/auto/network/socket/qtcpsocket/BLACKLIST index 07532710b31..129e9f0b4ea 100644 --- a/tests/auto/network/socket/qtcpsocket/BLACKLIST +++ b/tests/auto/network/socket/qtcpsocket/BLACKLIST @@ -1,10 +1,3 @@ -[bind] -windows-10 msvc-2015 -windows-7sp1 -[bind:[::]] -windows -[bind:[::]:randomport] -windows [timeoutConnect:ip] windows # QTBUG-66247 diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index 0546c6ba7d0..9374420f344 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -585,7 +585,7 @@ void tst_QTcpSocket::bind() if (successExpected) { bool randomPort = port == -1; - int attemptsLeft = 5; // only used with randomPort + int attemptsLeft = 5; // only used with randomPort or Windows do { if (randomPort) { // try to get a random port number From 210fd52e0d5e77105c676c064e7c3a69a00e2122 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 7 Feb 2020 09:47:24 -0800 Subject: [PATCH 10/28] Autotest: adapt to certain OSes always allowing binding to low ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apple changed on macOS 10.14 (Mojave). Windows has always allowed. Fixes: QTBUG-81905 Change-Id: I572733186b73423b89e5fffd15f12fee3f03c055 Reviewed-by: Tor Arne Vestbø --- tests/auto/network-settings.h | 16 ++++++++++++++++ .../tst_platformsocketengine.cpp | 13 +++++++++---- .../network/socket/qtcpsocket/tst_qtcpsocket.cpp | 16 ++++++++-------- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/tests/auto/network-settings.h b/tests/auto/network-settings.h index 77298342afc..4dd6ce897b8 100644 --- a/tests/auto/network-settings.h +++ b/tests/auto/network-settings.h @@ -134,6 +134,22 @@ public: return true; } + static bool canBindToLowPorts() + { +#ifdef Q_OS_UNIX + if (geteuid() == 0) + return true; + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) + return true; + // ### Which versions of iOS, watchOS and such does Apple's opening of + // all ports apply to? + return false; +#else + // Windows + return true; +#endif + } + #ifdef QT_NETWORK_LIB static bool verifyTestNetworkSettings() diff --git a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp index 5be00630ca6..68c913ecfc5 100644 --- a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp +++ b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp @@ -529,12 +529,11 @@ void tst_PlatformSocketEngine::tooManySockets() //--------------------------------------------------------------------------- void tst_PlatformSocketEngine::bind() { -#if !defined Q_OS_WIN PLATFORMSOCKETENGINE binder; QVERIFY(binder.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); - QVERIFY(!binder.bind(QHostAddress::AnyIPv4, 82)); - QCOMPARE(binder.error(), QAbstractSocket::SocketAccessError); -#endif + QCOMPARE(binder.bind(QHostAddress::AnyIPv4, 82), QtNetworkSettings::canBindToLowPorts()); + if (!QtNetworkSettings::canBindToLowPorts()) + QCOMPARE(binder.error(), QAbstractSocket::SocketAccessError); PLATFORMSOCKETENGINE binder2; QVERIFY(binder2.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); @@ -546,6 +545,12 @@ void tst_PlatformSocketEngine::bind() QCOMPARE(binder3.error(), QAbstractSocket::AddressInUseError); if (QtNetworkSettings::hasIPv6()) { + PLATFORMSOCKETENGINE binder; + QVERIFY(binder.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv6Protocol)); + QCOMPARE(binder.bind(QHostAddress::AnyIPv6, 82), QtNetworkSettings::canBindToLowPorts()); + if (!QtNetworkSettings::canBindToLowPorts()) + QCOMPARE(binder.error(), QAbstractSocket::SocketAccessError); + PLATFORMSOCKETENGINE binder4; QVERIFY(binder4.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv6Protocol)); QVERIFY(binder4.bind(QHostAddress::AnyIPv6, 31180)); diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index 9374420f344..5b3a17bdd77 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -523,7 +523,7 @@ void tst_QTcpSocket::bind_data() continue; // link-local bind will fail, at least on Linux, so skip it. QString ip(entry.ip().toString()); - QTest::newRow(ip.toLatin1().constData()) << ip << 0 << true << ip; + QTest::addRow("%s:0", ip.toLatin1().constData()) << ip << 0 << true << ip; if (!testIpv6 && entry.ip().protocol() == QAbstractSocket::IPv6Protocol) testIpv6 = true; @@ -531,9 +531,9 @@ void tst_QTcpSocket::bind_data() } // test binding to localhost - QTest::newRow("0.0.0.0") << "0.0.0.0" << 0 << true << "0.0.0.0"; + QTest::newRow("0.0.0.0:0") << "0.0.0.0" << 0 << true << "0.0.0.0"; if (testIpv6) - QTest::newRow("[::]") << "::" << 0 << true << "::"; + QTest::newRow("[::]:0") << "::" << 0 << true << "::"; // and binding with a port number... // Since we want to test that we got the port number we asked for, we need a random port number. @@ -551,16 +551,16 @@ void tst_QTcpSocket::bind_data() knownBad << "198.51.100.1"; knownBad << "2001:0DB8::1"; foreach (const QString &badAddress, knownBad) { - QTest::newRow(badAddress.toLatin1().constData()) << badAddress << 0 << false << QString(); + QTest::addRow("%s:0", badAddress.toLatin1().constData()) << badAddress << 0 << false << QString(); } -#ifdef Q_OS_UNIX // try to bind to a privileged ports // we should fail if we're not root (unless the ports are in use!) - QTest::newRow("127.0.0.1:1") << "127.0.0.1" << 1 << !geteuid() << (geteuid() ? QString() : "127.0.0.1"); + QTest::newRow("127.0.0.1:1") << "127.0.0.1" << 1 << QtNetworkSettings::canBindToLowPorts() + << (QtNetworkSettings::canBindToLowPorts() ? "127.0.0.1" : QString()); if (testIpv6) - QTest::newRow("[::]:1") << "::" << 1 << !geteuid() << (geteuid() ? QString() : "::"); -#endif + QTest::newRow("[::]:1") << "::" << 1 << QtNetworkSettings::canBindToLowPorts() + << (QtNetworkSettings::canBindToLowPorts() ? "::" : QString()); } void tst_QTcpSocket::bind() From c0c2efc3c62432b4ae159b911018682f573b54e4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 30 Jan 2020 14:46:37 -0800 Subject: [PATCH 11/28] QStringView: Fix warning about conversion from qsizetype to int Fixes: QTBUG-81764 Change-Id: If79a52e476594446baccfffd15eecb9d9e578118 Reviewed-by: Marc Mutz --- src/corelib/text/qstring.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h index 1669d7c94a8..3919dbf76c0 100644 --- a/src/corelib/text/qstring.h +++ b/src/corelib/text/qstring.h @@ -1122,7 +1122,7 @@ int QStringView::toWCharArray(wchar_t *array) const if (sizeof(wchar_t) == sizeof(QChar)) { if (auto src = data()) memcpy(array, src, sizeof(QChar) * size()); - return size(); + return int(size()); // ### q6sizetype } else { return QString::toUcs4_helper(reinterpret_cast(data()), int(size()), reinterpret_cast(array)); From 7af5619836cb3bd2eca87fd10b81674c9e201e76 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 29 Jan 2020 12:57:25 -0800 Subject: [PATCH 12/28] QLinkedListData: Move Q_CORE_EXPORT from class to shared_null This makes no difference for the IA-64 C++ ABI nor for MSVC until MSVC 2019 16.6. But it does with 16.6, where the std::atomic constructor becomes non-trivial, which makes QtPrivate::RefCount non-trivial, which makes QLinkedListData non-trivial. Before this change: User code \ Qt MSVC <=16.5 MSVC >=16.6 MSVC <=16.5 works works MSVC >=16.6 fails works With this change, they should all work. The list of symbols exported should not change either, so linking against a Qt compiled with MSVC <=16.5 should continue to work. [ChangeLog][MSVC] Fixed a compatibility issue found when linking code compiled with version 16.6 to a Qt compiled with 16.5. Fixes: QTBUG-81727 Change-Id: If79a52e476594446baccfffd15ee771397467f8b Reviewed-by: Simon Hausmann --- src/corelib/tools/qlinkedlist.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index 8970d39be0f..3b8c75b122b 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -58,14 +58,14 @@ QT_BEGIN_NAMESPACE -struct Q_CORE_EXPORT QLinkedListData +struct QLinkedListData { QLinkedListData *n, *p; QtPrivate::RefCount ref; int size; uint sharable : 1; - static const QLinkedListData shared_null; + Q_CORE_EXPORT static const QLinkedListData shared_null; }; template From 2a2ffe8a481c070002294c8762eff3c56ff3050a Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Wed, 12 Feb 2020 08:34:17 +0100 Subject: [PATCH 13/28] QUrl doc: Fix typo Change-Id: I76cd27ac07d09bd2ea9b818d34d1882230f66b10 Reviewed-by: Leena Miettinen --- src/corelib/io/qurl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 878e007fb0d..77bbd5f3e68 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -4189,7 +4189,7 @@ static bool isIp6(const QString &text) /*! Returns a valid URL from a user supplied \a userInput string if one can be - deducted. In the case that is not possible, an invalid QUrl() is returned. + deduced. In the case that is not possible, an invalid QUrl() is returned. This overload takes a \a workingDirectory path, in order to be able to handle relative paths. This is especially useful when handling command From 6c3bca01d908bcef149e7339a1268ce79fe8eefa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Tue, 11 Feb 2020 16:48:19 +0100 Subject: [PATCH 14/28] QNetConMonitor(Win): Account for LOCALNETWORK reachability What I originally thought NLM_CONNECTIVITY_IPV*_SUBNET meant turns out to be what NLM_CONNECTIVITY_IPV*_LOCALNETWORK is, leaving me to wonder when *_SUBNET is actually used. Anyway we now also check *_LOCALNETWORK to make sure we're not unnecessarily denying certain connections to be made. At the same time check for link-local connections where both local and remote are link-local, in this case even NLM_CONNECTIVITY_IPV*_NOTRAFFIC is valid. Unfortunately this check cannot be done in QNetworkStatusMonitor, so QNAM will likely not allow these connections. Task-number: QTBUG-80947 Change-Id: Ieb96ce9f4a478eef0c3ea47f2471f701c102b4d4 Reviewed-by: Timur Pocheptsov --- src/network/kernel/qnetconmonitor_win.cpp | 38 ++++++++++++++++++----- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/src/network/kernel/qnetconmonitor_win.cpp b/src/network/kernel/qnetconmonitor_win.cpp index 1566e7f914c..59b6cd5b666 100644 --- a/src/network/kernel/qnetconmonitor_win.cpp +++ b/src/network/kernel/qnetconmonitor_win.cpp @@ -163,11 +163,14 @@ private: ComPtr connectionEvents; // We can assume we have access to internet/subnet when this class is created because // connection has already been established to the peer: - NLM_CONNECTIVITY connectivity = - NLM_CONNECTIVITY(NLM_CONNECTIVITY_IPV4_INTERNET | NLM_CONNECTIVITY_IPV6_INTERNET - | NLM_CONNECTIVITY_IPV4_SUBNET | NLM_CONNECTIVITY_IPV6_SUBNET); + NLM_CONNECTIVITY connectivity = NLM_CONNECTIVITY( + NLM_CONNECTIVITY_IPV4_INTERNET | NLM_CONNECTIVITY_IPV6_INTERNET + | NLM_CONNECTIVITY_IPV4_SUBNET | NLM_CONNECTIVITY_IPV6_SUBNET + | NLM_CONNECTIVITY_IPV4_LOCALNETWORK | NLM_CONNECTIVITY_IPV6_LOCALNETWORK + | NLM_CONNECTIVITY_IPV4_NOTRAFFIC | NLM_CONNECTIVITY_IPV6_NOTRAFFIC); bool sameSubnet = false; + bool isLinkLocal = false; bool monitoring = false; bool comInitFailed = false; bool remoteIsIPv6 = false; @@ -370,6 +373,7 @@ bool QNetworkConnectionMonitorPrivate::setTargets(const QHostAddress &local, return false; } sameSubnet = remote.isInSubnet(local, it->prefixLength()); + isLinkLocal = remote.isLinkLocal() && local.isLinkLocal(); remoteIsIPv6 = remote.protocol() == QAbstractSocket::IPv6Protocol; return connectionEvents->setTarget(iface); @@ -461,9 +465,28 @@ void QNetworkConnectionMonitor::stopMonitoring() bool QNetworkConnectionMonitor::isReachable() { Q_D(QNetworkConnectionMonitor); - NLM_CONNECTIVITY required = d->sameSubnet - ? (d->remoteIsIPv6 ? NLM_CONNECTIVITY_IPV6_SUBNET : NLM_CONNECTIVITY_IPV4_SUBNET) - : (d->remoteIsIPv6 ? NLM_CONNECTIVITY_IPV6_INTERNET : NLM_CONNECTIVITY_IPV4_INTERNET); + + const NLM_CONNECTIVITY RequiredSameSubnetIPv6 = + NLM_CONNECTIVITY(NLM_CONNECTIVITY_IPV6_SUBNET | NLM_CONNECTIVITY_IPV6_LOCALNETWORK + | NLM_CONNECTIVITY_IPV6_INTERNET); + const NLM_CONNECTIVITY RequiredSameSubnetIPv4 = + NLM_CONNECTIVITY(NLM_CONNECTIVITY_IPV4_SUBNET | NLM_CONNECTIVITY_IPV4_LOCALNETWORK + | NLM_CONNECTIVITY_IPV4_INTERNET); + + NLM_CONNECTIVITY required; + if (d->isLinkLocal) { + required = NLM_CONNECTIVITY( + d->remoteIsIPv6 ? NLM_CONNECTIVITY_IPV6_NOTRAFFIC | RequiredSameSubnetIPv6 + : NLM_CONNECTIVITY_IPV4_NOTRAFFIC | RequiredSameSubnetIPv4); + } else if (d->sameSubnet) { + required = + NLM_CONNECTIVITY(d->remoteIsIPv6 ? RequiredSameSubnetIPv6 : RequiredSameSubnetIPv4); + + } else { + required = NLM_CONNECTIVITY(d->remoteIsIPv6 ? NLM_CONNECTIVITY_IPV6_INTERNET + : NLM_CONNECTIVITY_IPV4_INTERNET); + } + return d_func()->connectivity & required; } @@ -695,7 +718,8 @@ bool QNetworkStatusMonitor::isNetworkAccessible() { return d_func()->connectivity & (NLM_CONNECTIVITY_IPV4_INTERNET | NLM_CONNECTIVITY_IPV6_INTERNET - | NLM_CONNECTIVITY_IPV4_SUBNET | NLM_CONNECTIVITY_IPV6_SUBNET); + | NLM_CONNECTIVITY_IPV4_SUBNET | NLM_CONNECTIVITY_IPV6_SUBNET + | NLM_CONNECTIVITY_IPV4_LOCALNETWORK | NLM_CONNECTIVITY_IPV6_LOCALNETWORK); } bool QNetworkStatusMonitor::isEnabled() From c9eb9411cf901c6a9af5d470ebb5ba7ba7b7583a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Fri, 14 Feb 2020 12:26:23 +0100 Subject: [PATCH 15/28] QNAM: Correct logic of network monitor when bearer is disabled Change-Id: I0abe9034874a80423ad1e332404236dc5ff54365 Reviewed-by: Timur Pocheptsov --- src/network/access/qnetworkaccessmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 76b95b5823f..89664c154fa 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1462,7 +1462,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera // immediately set 'networkAccessible' even before we start // the monitor. #ifdef QT_NO_BEARERMANAGEMENT - if (d->networkAccessible + if (!d->networkAccessible #else if (d->networkAccessible == NotAccessible #endif // QT_NO_BEARERMANAGEMENT From b26b40f7e1f67dd3de1c81bd022aa202b5b5cad5 Mon Sep 17 00:00:00 2001 From: Paul Wicking Date: Fri, 14 Feb 2020 05:27:06 +0100 Subject: [PATCH 16/28] Doc: remove link to Qt Quarterly in example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Qt Quarterly 31 was the last edition of Qt Quarterly to be published exclusively as a PDF. We cannot fix the typo in the PDF. As the content is >10 years old an in an unmaintained archive section, remove the reference to it from this example. Fixes: QTBUG-81972 Change-Id: I41a82487ff89dbe8ea5701c02c51e7f7c79bf73d Reviewed-by: Leena Miettinen Reviewed-by: Topi Reiniö --- examples/widgets/doc/src/syntaxhighlighter.qdoc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/widgets/doc/src/syntaxhighlighter.qdoc b/examples/widgets/doc/src/syntaxhighlighter.qdoc index 8583d861140..618b387ed58 100644 --- a/examples/widgets/doc/src/syntaxhighlighter.qdoc +++ b/examples/widgets/doc/src/syntaxhighlighter.qdoc @@ -246,11 +246,7 @@ \section1 Other Code Editor Features - It is possible to implement parenthesis matching with - QSyntaxHighlighter. The "Matching Parentheses with - QSyntaxHighlighter" article in Qt Quarterly 31 - (\l{http://doc.qt.io/archives/qq/}) implements this. We also have - the \l{Code Editor Example}, which shows how to implement line + The \l{Code Editor Example} shows how to implement line numbers and how to highlight the current line. */ From 115e39f9be99069dcb96579064e78b9a8f5468fc Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 28 Jan 2020 18:00:20 +0100 Subject: [PATCH 17/28] Avoid return QImage::Format_Invalid from QPlatformScreen::format() This can be used to set the pixmap format, and needs to be defined to something sane even if there is no primary screen. Task-number: QTBUG-81671 Change-Id: Ic0d41cec31ac71309123aa8bb8b840fa4a4122bb Reviewed-by: Eirik Aavitsland --- src/plugins/platforms/xcb/qxcbscreen.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index e937464c624..87e1c9bdf84 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -665,7 +665,9 @@ QImage::Format QXcbScreen::format() const bool needsRgbSwap; qt_xcb_imageFormatForVisual(connection(), screen()->root_depth, visualForId(screen()->root_visual), &format, &needsRgbSwap); // We are ignoring needsRgbSwap here and just assumes the backing-store will handle it. - return format; + if (format != QImage::Format_Invalid) + return format; + return QImage::Format_RGB32; } int QXcbScreen::forcedDpi() const From 6a56862a2214e4ff1743fc3ce97427a30475b48a Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Wed, 12 Feb 2020 15:13:57 +0100 Subject: [PATCH 18/28] QAbstractItemView: do not request illegal model indexes If a model is empty, there is no index (0, 0); requesting it is undefined behavior. Rather than protecting the calls with checks on rowCount/columnCount, remove the Q_ASSERTs altogether: they're trying to do some basic sanity checks on the model, something that doesn't belong to a view (but, say, to QAbstractItemModelTester). Change-Id: I0ea25604fdcf524a10f5922a03a4d0700447f6a7 Reviewed-by: Andre Somers Reviewed-by: Richard Moe Gustavsen --- src/widgets/itemviews/qabstractitemview.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index b07faf8be4d..c3f8dd894e7 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -705,15 +705,6 @@ void QAbstractItemView::setModel(QAbstractItemModel *model) } d->model = (model ? model : QAbstractItemModelPrivate::staticEmptyModel()); - // These asserts do basic sanity checking of the model - Q_ASSERT_X(d->model->index(0,0) == d->model->index(0,0), - "QAbstractItemView::setModel", - "A model should return the exact same index " - "(including its internal id/pointer) when asked for it twice in a row."); - Q_ASSERT_X(!d->model->index(0,0).parent().isValid(), - "QAbstractItemView::setModel", - "The parent of a top level index should be invalid"); - if (d->model != QAbstractItemModelPrivate::staticEmptyModel()) { connect(d->model, SIGNAL(destroyed()), this, SLOT(_q_modelDestroyed())); From 81bd1bba7b67716ed0ae565061ebedc5a5455a40 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 12 Feb 2020 15:27:27 +0100 Subject: [PATCH 19/28] Windows: Add install/uninstall rules for target.targets Mirror the behavior in unixmake.cpp and do actually install /uninstall files in target.targets. This fixes the installation of .debug files on MinGW for a Qt with -force-debug-info -separate-debug-info. [ChangeLog][qmake] Install/uninstall rules are now generated for target.targets on Windows. This mirrors the behavior on Unix. Fixes: QTBUG-81354 Change-Id: Ie9366f132ebd8e18680f32f2e52cec64dbd87e9a Reviewed-by: Joerg Bornemann --- qmake/generators/win32/winmakefile.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 86d10c213cc..3ec2704625e 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -736,6 +736,18 @@ QString Win32MakefileGenerator::defaultInstall(const QString &t) if(targetdir.right(1) != Option::dir_sep) targetdir += Option::dir_sep; + const ProStringList &targets = project->values(ProKey(t + ".targets")); + for (int i = 0; i < targets.size(); ++i) { + QString src = targets.at(i).toQString(), + dst = escapeFilePath(filePrefixRoot(root, targetdir + src.section('/', -1))); + if (!ret.isEmpty()) + ret += "\n\t"; + ret += "$(QINSTALL) " + escapeFilePath(Option::fixPathToTargetOS(src, false)) + ' ' + dst; + if (!uninst.isEmpty()) + uninst.append("\n\t"); + uninst.append("-$(DEL_FILE) " + dst); + } + if(t == "target" && project->first("TEMPLATE") == "lib") { if(project->isActiveConfig("create_prl") && !project->isActiveConfig("no_install_prl") && !project->isEmpty("QMAKE_INTERNAL_PRL_FILE")) { @@ -744,6 +756,8 @@ QString Win32MakefileGenerator::defaultInstall(const QString &t) if(slsh != -1) dst_prl = dst_prl.right(dst_prl.length() - slsh - 1); dst_prl = filePrefixRoot(root, targetdir + dst_prl); + if (!ret.isEmpty()) + ret += "\n\t"; ret += installMetaFile(ProKey("QMAKE_PRL_INSTALL_REPLACE"), project->first("QMAKE_INTERNAL_PRL_FILE").toQString(), dst_prl); if(!uninst.isEmpty()) uninst.append("\n\t"); From 1c0b69eac521fec074390c023be8b5a23e88dd50 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 5 Feb 2020 15:42:41 +0100 Subject: [PATCH 20/28] Only read the first BOM as a BOM; the rest are ZWNBS ! QUtf32::convertToUnicode() was forgetting to set headerdone when it dealt with the header (for contrast, Utf16::convertToUnicode() does). Fixes: QTBUG-62011 Change-Id: Ia254782ce0967a6cf9ce0e81eb06d41521150eed Reviewed-by: Qt CI Bot Reviewed-by: Lars Knoll --- src/corelib/codecs/qutfcodec.cpp | 1 + tests/auto/corelib/text/qstring/tst_qstring.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp index af36bd7e2fa..8561f908b94 100644 --- a/src/corelib/codecs/qutfcodec.cpp +++ b/src/corelib/codecs/qutfcodec.cpp @@ -930,6 +930,7 @@ QString QUtf32::convertToUnicode(const char *chars, int len, QTextCodec::Convert tuple[num++] = *chars++; if (num == 4) { if (!headerdone) { + headerdone = true; if (endian == DetectEndianness) { if (tuple[0] == 0xff && tuple[1] == 0xfe && tuple[2] == 0 && tuple[3] == 0 && endian != BigEndianness) { endian = LittleEndianness; diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp index 7ea93a87d61..3714e854f74 100644 --- a/tests/auto/corelib/text/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -4704,6 +4704,12 @@ void tst_QString::fromUcs4() s = QString::fromUcs4(U"\u221212\U000020AC\U00010000"); QCOMPARE(s, QString::fromUtf8("\342\210\222" "12" "\342\202\254" "\360\220\200\200")); #endif + + // QTBUG-62011: don't mistake ZWNBS for BOM + // Start with one BOM, to ensure we use the right endianness: + const uint text[] = { 0xfeff, 97, 0xfeff, 98, 0xfeff, 99, 0xfeff, 100 }; + s = QString::fromUcs4(text, 8); + QCOMPARE(s, QStringView(u"a\xfeff" u"b\xfeff" u"c\xfeff" "d")); } void tst_QString::toUcs4() From 2865a58a2ae39d795f1ec18cacb2af8053599256 Mon Sep 17 00:00:00 2001 From: Lorn Potter Date: Tue, 8 Oct 2019 11:18:46 +1000 Subject: [PATCH 21/28] wasm: fix crash when qtvkb tries to load a plugin We do not have dlopen, harfbuzz seems to try and load the thai plugin using dlopen when just iterating through the language selector in virtualkeyboard.. Fixes: QTBUG-78825 Change-Id: Iee064a1d9a628784e3ce46d641cd157a69bcb696 Reviewed-by: Volker Hilsheimer --- src/corelib/text/qharfbuzz.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/text/qharfbuzz.cpp b/src/corelib/text/qharfbuzz.cpp index a3e266ccd27..f54ce262068 100644 --- a/src/corelib/text/qharfbuzz.cpp +++ b/src/corelib/text/qharfbuzz.cpp @@ -72,7 +72,7 @@ HB_UChar16 HB_GetMirroredChar(HB_UChar16 ch) void (*HB_Library_Resolve(const char *library, int version, const char *symbol))() { -#if !QT_CONFIG(library) +#if !QT_CONFIG(library) || defined(Q_OS_WASM) Q_UNUSED(library); Q_UNUSED(version); Q_UNUSED(symbol); From 1635848d87d7720958721e76fdf2f20bfae393ad Mon Sep 17 00:00:00 2001 From: Lorn Potter Date: Fri, 31 Jan 2020 08:14:51 +1000 Subject: [PATCH 22/28] wasm: remove dependency on perl to find emscripten version Change-Id: I0d5224d497b2b5652d1be036f2a90c6c53f0c9df Fixes: QTBUG-81722 Reviewed-by: Joerg Bornemann --- mkspecs/features/wasm/emcc_ver.prf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mkspecs/features/wasm/emcc_ver.prf b/mkspecs/features/wasm/emcc_ver.prf index 505a321d641..411f53e95de 100644 --- a/mkspecs/features/wasm/emcc_ver.prf +++ b/mkspecs/features/wasm/emcc_ver.prf @@ -3,7 +3,9 @@ defineReplace(qtEmccRecommendedVersion) { } defineReplace(qtSystemEmccVersion) { - E_VERSION = $$system("emcc -v 2>&1 | perl -alne $$shell_quote($_ = $F[9]; s/://; print;) ") + EMCC = $$system("emcc -v 2>&1", lines) + EMCC_LINE = $$find(EMCC, "^.*\b(emcc)\b.*$") + E_VERSION = $$section(EMCC_LINE, " ", 9,9) return ($${E_VERSION}) } From 27d35a3ed0d71fd2ad5f213591172c85a767f5ca Mon Sep 17 00:00:00 2001 From: Nicolas Guichard Date: Mon, 17 Feb 2020 13:19:45 +0100 Subject: [PATCH 23/28] QShaderGraph: Fix statement creation for graphs with dangling branches For graphs like this one: Input ----> Function1 ----> Output \ ---> Function2 (unbound output) We would have generated only 2 statements, for Function1 and Output. This change fixes this by treating Function2 like an output. Therefore it generates 4 statements: Input, Function1, Output and Function2. Change-Id: Iaada40b9b949d771806dd47efad4f7ef2a775b48 Reviewed-by: Paul Lemire --- src/gui/util/qshadergraph.cpp | 17 ++++--- .../util/qshadergraph/tst_qshadergraph.cpp | 45 +++++++++++++++++++ 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/gui/util/qshadergraph.cpp b/src/gui/util/qshadergraph.cpp index b05b7107136..46fe6ac6d67 100644 --- a/src/gui/util/qshadergraph.cpp +++ b/src/gui/util/qshadergraph.cpp @@ -44,13 +44,20 @@ QT_BEGIN_NAMESPACE namespace { - QVector copyOutputNodes(const QVector &nodes) + QVector copyOutputNodes(const QVector &nodes, const QVector &edges) { auto res = QVector(); std::copy_if(nodes.cbegin(), nodes.cend(), std::back_inserter(res), - [] (const QShaderNode &node) { - return node.type() == QShaderNode::Output; + [&edges] (const QShaderNode &node) { + return node.type() == QShaderNode::Output || + (node.type() == QShaderNode::Function && + !std::any_of(edges.cbegin(), + edges.cend(), + [&node] (const QShaderGraph::Edge &edge) { + return edge.sourceNodeUuid == + node.uuid(); + })); }); return res; } @@ -210,8 +217,8 @@ QVector QShaderGraph::createStatements(const QStringLis auto result = QVector(); QVector currentEdges = enabledEdges; - QVector currentUuids = [enabledNodes] { - const QVector inputs = copyOutputNodes(enabledNodes); + QVector currentUuids = [enabledNodes, enabledEdges] { + const QVector inputs = copyOutputNodes(enabledNodes, enabledEdges); auto res = QVector(); std::transform(inputs.cbegin(), inputs.cend(), std::back_inserter(res), diff --git a/tests/auto/gui/util/qshadergraph/tst_qshadergraph.cpp b/tests/auto/gui/util/qshadergraph/tst_qshadergraph.cpp index ce2d38c24fd..50c925a1111 100644 --- a/tests/auto/gui/util/qshadergraph/tst_qshadergraph.cpp +++ b/tests/auto/gui/util/qshadergraph/tst_qshadergraph.cpp @@ -114,6 +114,7 @@ private slots: void shouldSurviveCyclesDuringGraphSerialization(); void shouldDealWithEdgesJumpingOverLayers(); void shouldGenerateDifferentStatementsDependingOnActiveLayers(); + void shouldDealWithBranchesWithoutOutput(); }; void tst_QShaderGraph::shouldHaveEdgeDefaultState() @@ -774,6 +775,50 @@ void tst_QShaderGraph::shouldGenerateDifferentStatementsDependingOnActiveLayers( } } +void tst_QShaderGraph::shouldDealWithBranchesWithoutOutput() +{ + // GIVEN + const auto input = createNode({ + createPort(QShaderNodePort::Output, "input") + }); + const auto output = createNode({ + createPort(QShaderNodePort::Input, "output") + }); + const auto danglingFunction = createNode({ + createPort(QShaderNodePort::Input, "functionInput"), + createPort(QShaderNodePort::Output, "unbound") + }); + const auto function = createNode({ + createPort(QShaderNodePort::Input, "functionInput"), + createPort(QShaderNodePort::Output, "functionOutput") + }); + + const auto graph = [=] { + auto res = QShaderGraph(); + res.addNode(input); + res.addNode(function); + res.addNode(danglingFunction); + res.addNode(output); + res.addEdge(createEdge(input.uuid(), "input", function.uuid(), "functionInput")); + res.addEdge(createEdge(input.uuid(), "input", danglingFunction.uuid(), "functionInput")); + res.addEdge(createEdge(function.uuid(), "functionOutput", output.uuid(), "output")); + return res; + }(); + + // WHEN + const auto statements = graph.createStatements(); + + // THEN + // Note that no edge leads to the unbound input + const auto expected = QVector() + << createStatement(input, {}, {0}) + << createStatement(function, {0}, {1}) + << createStatement(output, {1}, {}) + << createStatement(danglingFunction, {0}, {2}); + dumpStatementsIfNeeded(statements, expected); + QCOMPARE(statements, expected); +} + QTEST_MAIN(tst_QShaderGraph) #include "tst_qshadergraph.moc" From c6da278271a2a3627b7a9933776cbdffc5bd2f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 31 Jan 2020 11:31:03 +0000 Subject: [PATCH 24/28] wasm: Specify event targets by CSS selectors; Support emsdk >= 1.39.5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR is now on by default, which means that functions like emscripten_set_keydown_callback() now expects CSS selectors (e.g. "#canvas_id" instead of "canvas_id"). In addition, Module.canvas is no more. Add a deprecation warning in case someone is setting it and expects Qt to use it. (qtloader.js sets qtCanvasElements instead). This bumps the minimum supported emsdk version to 1.39.5. Change-Id: I38abb2a191076ea04581c29552657ee3e0b87dbc Reviewed-by: Morten Johan Sørvig --- .../platforms/wasm/qwasmeventtranslator.cpp | 25 +++++++++---------- .../platforms/wasm/qwasmintegration.cpp | 9 ++++--- .../platforms/wasm/qwasmopenglcontext.cpp | 3 ++- src/plugins/platforms/wasm/qwasmscreen.cpp | 4 +-- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp index 1ccac87afa0..d515a8cd2fb 100644 --- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp +++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp @@ -339,8 +339,7 @@ QWasmEventTranslator::QWasmEventTranslator(QWasmScreen *screen) void QWasmEventTranslator::initEventHandlers() { - QByteArray _canvasId = screen()->canvasId().toUtf8(); - const char *canvasId = _canvasId.constData(); + QByteArray canvasSelector = "#" + screen()->canvasId().toUtf8(); // The Platform Detect: expand coverage and move as needed enum Platform { @@ -364,21 +363,21 @@ void QWasmEventTranslator::initEventHandlers() } } - emscripten_set_keydown_callback(canvasId, (void *)this, 1, &keyboard_cb); - emscripten_set_keyup_callback(canvasId, (void *)this, 1, &keyboard_cb); + emscripten_set_keydown_callback(canvasSelector.constData(), (void *)this, 1, &keyboard_cb); + emscripten_set_keyup_callback(canvasSelector.constData(), (void *)this, 1, &keyboard_cb); - emscripten_set_mousedown_callback(canvasId, (void *)this, 1, &mouse_cb); - emscripten_set_mouseup_callback(canvasId, (void *)this, 1, &mouse_cb); - emscripten_set_mousemove_callback(canvasId, (void *)this, 1, &mouse_cb); + emscripten_set_mousedown_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb); + emscripten_set_mouseup_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb); + emscripten_set_mousemove_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb); - emscripten_set_focus_callback(canvasId, (void *)this, 1, &focus_cb); + emscripten_set_focus_callback(canvasSelector.constData(), (void *)this, 1, &focus_cb); - emscripten_set_wheel_callback(canvasId, (void *)this, 1, &wheel_cb); + emscripten_set_wheel_callback(canvasSelector.constData(), (void *)this, 1, &wheel_cb); - emscripten_set_touchstart_callback(canvasId, (void *)this, 1, &touchCallback); - emscripten_set_touchend_callback(canvasId, (void *)this, 1, &touchCallback); - emscripten_set_touchmove_callback(canvasId, (void *)this, 1, &touchCallback); - emscripten_set_touchcancel_callback(canvasId, (void *)this, 1, &touchCallback); + emscripten_set_touchstart_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback); + emscripten_set_touchend_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback); + emscripten_set_touchmove_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback); + emscripten_set_touchcancel_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback); } template diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp index ee3f6afb731..9934f5ac19a 100644 --- a/src/plugins/platforms/wasm/qwasmintegration.cpp +++ b/src/plugins/platforms/wasm/qwasmintegration.cpp @@ -108,9 +108,8 @@ QWasmIntegration::QWasmIntegration() s_instance = this; // We expect that qtloader.js has populated Module.qtCanvasElements with one or more canvases. - // Also check Module.canvas, which may be set if the emscripen or a custom loader is used. emscripten::val qtCanvaseElements = val::module_property("qtCanvasElements"); - emscripten::val canvas = val::module_property("canvas"); + emscripten::val canvas = val::module_property("canvas"); // TODO: remove for Qt 6.0 if (!qtCanvaseElements.isUndefined()) { int screenCount = qtCanvaseElements["length"].as(); @@ -119,7 +118,9 @@ QWasmIntegration::QWasmIntegration() QString canvasId = QWasmString::toQString(canvas["id"]); addScreen(canvasId); } - } else if (!canvas.isUndefined()){ + } else if (!canvas.isUndefined()) { + qWarning() << "Module.canvas is deprecated. A future version of Qt will stop reading this property. " + << "Instead, set Module.qtCanvasElements to be an array of canvas elements, or use qtloader.js."; QString canvasId = QWasmString::toQString(canvas["id"]); addScreen(canvasId); } @@ -139,7 +140,7 @@ QWasmIntegration::QWasmIntegration() integration->resizeAllScreens(); return 0; }; - emscripten_set_resize_callback(nullptr, nullptr, 1, onWindowResize); + emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, 1, onWindowResize); } QWasmIntegration::~QWasmIntegration() diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp index 501ab99116a..4ddd56fd8ca 100644 --- a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp +++ b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp @@ -106,7 +106,8 @@ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(cons attributes.depth = useDepthStencil; attributes.stencil = useDepthStencil; - EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context(canvasId.toUtf8().constData(), &attributes); + QByteArray convasSelector = "#" + canvasId.toUtf8(); + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context(convasSelector.constData(), &attributes); return context; } diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp index d407111c2f9..2788f1ac190 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.cpp +++ b/src/plugins/platforms/wasm/qwasmscreen.cpp @@ -178,10 +178,10 @@ void QWasmScreen::updateQScreenAndCanvasRenderSize() // Setting the render size to a value larger than the CSS size enables high-dpi // rendering. - QByteArray canvasId = m_canvasId.toUtf8(); + QByteArray canvasSelector = "#" + m_canvasId.toUtf8(); double css_width; double css_height; - emscripten_get_element_css_size(canvasId.constData(), &css_width, &css_height); + emscripten_get_element_css_size(canvasSelector.constData(), &css_width, &css_height); QSizeF cssSize(css_width, css_height); QSizeF canvasSize = cssSize * devicePixelRatio(); From b84704e208550af5e257ee8b50f5858e4b148f23 Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Mon, 17 Feb 2020 10:16:18 +0800 Subject: [PATCH 25/28] Fix typo in QGuiApplication's documentation Change-Id: Ie6a05c8d71b81777ae79a5ff3db380b284d56313 Reviewed-by: Friedemann Kleint --- src/gui/kernel/qguiapplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 2b3299f745a..4bb25075212 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -610,7 +610,7 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME \li \c {dialogs=[xp|none]}, \c xp uses XP-style native dialogs and \c none disables them. - \li \c {dpiawareness=[0|1|2} Sets the DPI awareness of the process + \li \c {dpiawareness=[0|1|2]} Sets the DPI awareness of the process (see \l{High DPI Displays}, since Qt 5.4). \li \c {fontengine=freetype}, uses the FreeType font engine. \li \c {menus=[native|none]}, controls the use of native menus. From 51cc564c500fdbca9d3b6526931213c9679f849b Mon Sep 17 00:00:00 2001 From: Lorn Potter Date: Mon, 20 Jan 2020 20:33:07 +1000 Subject: [PATCH 26/28] wasm: guard nonthreaded builds from using threading.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ib5cd8afc4822cc89371d184ee5645ed8f496c8b0 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/wasm/qwasmeventdispatcher.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp b/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp index d89cd78b285..ca8db9b2154 100644 --- a/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp +++ b/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp @@ -33,9 +33,11 @@ #include +#if QT_CONFIG(thread) #if (__EMSCRIPTEN_major__ > 1 || __EMSCRIPTEN_minor__ > 38 || __EMSCRIPTEN_minor__ == 38 && __EMSCRIPTEN_tiny__ >= 22) # define EMSCRIPTEN_HAS_ASYNC_RUN_IN_MAIN_RUNTIME_THREAD #endif +#endif #ifdef EMSCRIPTEN_HAS_ASYNC_RUN_IN_MAIN_RUNTIME_THREAD #include From 1538395e3f0ace5c4ace01f41be00be149624c6a Mon Sep 17 00:00:00 2001 From: Lorn Potter Date: Fri, 3 Jan 2020 13:13:28 +1000 Subject: [PATCH 27/28] wasm: futureproof EmscriptenMouseEvent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Future versions of emscripten will remove the timestamp, so we need to replace this with the current timestamp See https://github.com/emscripten-core/emscripten/commit/a7f058a1e6e4b72b4446a3b36f8e96f9f8f41f2d#diff-9a5d68085dc7db2938b37a2b7b05c1f5 Change-Id: I8379d1adee1df1084461fddb1dd2e71684de9657 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/wasm/qwasmeventtranslator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp index d515a8cd2fb..62ada796db3 100644 --- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp +++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp @@ -547,7 +547,7 @@ void resizeWindow(QWindow *window, QWasmWindow::ResizeMode mode, void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent) { - auto timestamp = mouseEvent->timestamp; + auto timestamp = emscripten_date_now(); QPoint targetPoint(mouseEvent->targetX, mouseEvent->targetY); QPoint globalPoint = screen()->geometry().topLeft() + targetPoint; @@ -673,7 +673,7 @@ int QWasmEventTranslator::wheel_cb(int eventType, const EmscriptenWheelEvent *wh QWasmEventTranslator *translator = (QWasmEventTranslator*)userData; Qt::KeyboardModifiers modifiers = translator->translateMouseEventModifier(&mouseEvent); - auto timestamp = mouseEvent.timestamp; + auto timestamp = emscripten_date_now(); QPoint targetPoint(mouseEvent.targetX, mouseEvent.targetY); QPoint globalPoint = eventTranslator->screen()->geometry().topLeft() + targetPoint; From d7b6c4288f2de8b0123c888e83a3fbcd84ed906f Mon Sep 17 00:00:00 2001 From: Lorn Potter Date: Tue, 9 Oct 2018 10:14:43 +1000 Subject: [PATCH 28/28] wasm: add platform qsettings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the backend is async, the settings will not be ready to read/write instantly as on other platforms, but only be ready after the filesystem has been synced to the sandbox. This takes at least 250 to 500 ms. The QSettings status() or isWritable() can be used to discern when the settings are ready for use. This also fixes a crash in threaded wasm Task-number: QTBUG-70002 Change-Id: I080bdb940aa8e9a126d7358b524f32477db151b6 Reviewed-by: Morten Johan Sørvig --- src/corelib/io/io.pri | 1 + src/corelib/io/qsettings.cpp | 15 +- src/corelib/io/qsettings_p.h | 13 +- src/corelib/io/qsettings_wasm.cpp | 259 ++++++++++++++++++++++++ src/corelib/kernel/qcoreapplication.cpp | 19 +- src/gui/kernel/qguiapplication.cpp | 8 +- 6 files changed, 277 insertions(+), 38 deletions(-) create mode 100644 src/corelib/io/qsettings_wasm.cpp diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index fe816899324..c4c6f413875 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -136,6 +136,7 @@ qtConfig(settings) { } else: darwin:!nacl { SOURCES += io/qsettings_mac.cpp } + wasm : SOURCES += io/qsettings_wasm.cpp } win32 { diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index fc7122d904d..dcc93404734 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -76,10 +76,6 @@ # include #endif -#ifdef Q_OS_WASM -#include -#endif - #include #include @@ -295,7 +291,7 @@ after_loop: // see also qsettings_win.cpp, qsettings_winrt.cpp and qsettings_mac.cpp -#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) +#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) && !defined(Q_OS_WASM) QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope, const QString &organization, const QString &application) { @@ -1185,7 +1181,9 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format, confFiles.append(QConfFile::fromName(systemPath.path + orgFile, false)); } +#ifndef Q_OS_WASM // wasm needs to delay access until after file sync initAccess(); +#endif } QConfFileSettingsPrivate::QConfFileSettingsPrivate(const QString &fileName, @@ -1548,13 +1546,6 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile) perms |= QFile::ReadGroup | QFile::ReadOther; QFile(confFile->name).setPermissions(perms); } -#ifdef Q_OS_WASM - EM_ASM( - // Sync sandbox filesystem to persistent database filesystem. See QTBUG-70002 - FS.syncfs(false, function(err) { - }); - ); -#endif } else { setStatus(QSettings::AccessError); } diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h index d18c96a06c9..c30f099a72c 100644 --- a/src/corelib/io/qsettings_p.h +++ b/src/corelib/io/qsettings_p.h @@ -57,6 +57,10 @@ #include "QtCore/qiodevice.h" #include "QtCore/qstack.h" #include "QtCore/qstringlist.h" + +#include +#include "qsettings.h" + #ifndef QT_NO_QOBJECT #include "private/qobject_p.h" #endif @@ -253,6 +257,10 @@ protected: mutable QSettings::Status status; }; +#ifdef Q_OS_WASM +class QWasmSettingsPrivate; +#endif + class QConfFileSettingsPrivate : public QSettingsPrivate { public: @@ -281,7 +289,7 @@ public: private: void initFormat(); - void initAccess(); + virtual void initAccess(); void syncConfFile(QConfFile *confFile); bool writeIniFile(QIODevice &device, const ParsedSettingsMap &map); #ifdef Q_OS_MAC @@ -297,6 +305,9 @@ private: QString extension; Qt::CaseSensitivity caseSensitivity; int nextPosition; +#ifdef Q_OS_WASM + friend class QWasmSettingsPrivate; +#endif }; QT_END_NAMESPACE diff --git a/src/corelib/io/qsettings_wasm.cpp b/src/corelib/io/qsettings_wasm.cpp new file mode 100644 index 00000000000..8d8f4b505cd --- /dev/null +++ b/src/corelib/io/qsettings_wasm.cpp @@ -0,0 +1,259 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module 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 "qsettings.h" +#ifndef QT_NO_SETTINGS + +#include "qsettings_p.h" +#ifndef QT_NO_QOBJECT +#include "qcoreapplication.h" +#include +#endif // QT_NO_QOBJECT +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +static bool isReadReady = false; + +class QWasmSettingsPrivate : public QConfFileSettingsPrivate +{ +public: + QWasmSettingsPrivate(QSettings::Scope scope, const QString &organization, + const QString &application); + ~QWasmSettingsPrivate(); + + bool get(const QString &key, QVariant *value) const override; + QStringList children(const QString &prefix, ChildSpec spec) const override; + void clear() override; + void sync() override; + void flush() override; + bool isWritable() const override; + + void syncToLocal(const char *data, int size); + void loadLocal(const QByteArray &filename); + void setReady(); + void initAccess() override; + +private: + QString databaseName; + QString id; +}; + +static void QWasmSettingsPrivate_onLoad(void *userData, void *dataPtr, int size) +{ + QWasmSettingsPrivate *wasm = reinterpret_cast(userData); + + QFile file(wasm->fileName()); + QFileInfo fileInfo(wasm->fileName()); + QDir dir(fileInfo.path()); + if (!dir.exists()) + dir.mkpath(fileInfo.path()); + + if (file.open(QFile::WriteOnly)) { + file.write(reinterpret_cast(dataPtr), size); + file.close(); + wasm->setReady(); + } +} + +static void QWasmSettingsPrivate_onError(void *userData) +{ + QWasmSettingsPrivate *wasm = reinterpret_cast(userData); + if (wasm) + wasm->setStatus(QSettings::AccessError); +} + +static void QWasmSettingsPrivate_onStore(void *userData) +{ + QWasmSettingsPrivate *wasm = reinterpret_cast(userData); + if (wasm) + wasm->setStatus(QSettings::NoError); +} + +static void QWasmSettingsPrivate_onCheck(void *userData, int exists) +{ + QWasmSettingsPrivate *wasm = reinterpret_cast(userData); + if (wasm) { + if (exists) + wasm->loadLocal(wasm->fileName().toLocal8Bit()); + else + wasm->setReady(); + } +} + +QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, + QSettings::Scope scope, + const QString &organization, + const QString &application) +{ + Q_UNUSED(format) + if (organization == QLatin1String("Qt")) + { + QString organizationDomain = QCoreApplication::organizationDomain(); + QString applicationName = QCoreApplication::applicationName(); + + QSettingsPrivate *newSettings; + newSettings = new QWasmSettingsPrivate(scope, organizationDomain, applicationName); + + newSettings->beginGroupOrArray(QSettingsGroup(normalizedKey(organization))); + if (!application.isEmpty()) + newSettings->beginGroupOrArray(QSettingsGroup(normalizedKey(application))); + + return newSettings; + } + return new QWasmSettingsPrivate(scope, organization, application); +} + +QWasmSettingsPrivate::QWasmSettingsPrivate(QSettings::Scope scope, const QString &organization, + const QString &application) + : QConfFileSettingsPrivate(QSettings::NativeFormat, scope, organization, application) +{ + setStatus(QSettings::AccessError); // access error until sandbox gets loaded + databaseName = organization; + id = application; + + emscripten_idb_async_exists("/home/web_user", + fileName().toLocal8Bit(), + reinterpret_cast(this), + QWasmSettingsPrivate_onCheck, + QWasmSettingsPrivate_onError); +} + +QWasmSettingsPrivate::~QWasmSettingsPrivate() +{ +} + + void QWasmSettingsPrivate::initAccess() +{ + if (isReadReady) + QConfFileSettingsPrivate::initAccess(); +} + +bool QWasmSettingsPrivate::get(const QString &key, QVariant *value) const +{ + if (isReadReady) + return QConfFileSettingsPrivate::get(key, value); + + return false; +} + +QStringList QWasmSettingsPrivate::children(const QString &prefix, ChildSpec spec) const +{ + return QConfFileSettingsPrivate::children(prefix, spec); +} + +void QWasmSettingsPrivate::clear() +{ + QConfFileSettingsPrivate::clear(); + emscripten_idb_async_delete("/home/web_user", + fileName().toLocal8Bit(), + reinterpret_cast(this), + QWasmSettingsPrivate_onStore, + QWasmSettingsPrivate_onError); +} + +void QWasmSettingsPrivate::sync() +{ + QConfFileSettingsPrivate::sync(); + + QFile file(fileName()); + if (file.open(QFile::ReadOnly)) { + QByteArray dataPointer = file.readAll(); + + emscripten_idb_async_store("/home/web_user", + fileName().toLocal8Bit(), + reinterpret_cast(dataPointer.data()), + dataPointer.length(), + reinterpret_cast(this), + QWasmSettingsPrivate_onStore, + QWasmSettingsPrivate_onError); + } +} + +void QWasmSettingsPrivate::flush() +{ + sync(); +} + +bool QWasmSettingsPrivate::isWritable() const +{ + return isReadReady && QConfFileSettingsPrivate::isWritable(); +} + +void QWasmSettingsPrivate::syncToLocal(const char *data, int size) +{ + QFile file(fileName()); + + if (file.open(QFile::WriteOnly)) { + file.write(data, size + 1); + QByteArray data = file.readAll(); + + emscripten_idb_async_store("/home/web_user", + fileName().toLocal8Bit(), + reinterpret_cast(data.data()), + data.length(), + reinterpret_cast(this), + QWasmSettingsPrivate_onStore, + QWasmSettingsPrivate_onError); + setReady(); + } +} + +void QWasmSettingsPrivate::loadLocal(const QByteArray &filename) +{ + emscripten_idb_async_load("/home/web_user", + filename.data(), + reinterpret_cast(this), + QWasmSettingsPrivate_onLoad, + QWasmSettingsPrivate_onError); +} + +void QWasmSettingsPrivate::setReady() +{ + isReadReady = true; + setStatus(QSettings::NoError); + QConfFileSettingsPrivate::initAccess(); +} + +QT_END_NAMESPACE +#endif // QT_NO_SETTINGS diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index e25049f8213..70f0a5ad4ca 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -121,7 +121,6 @@ #endif #ifdef Q_OS_WASM -#include #include #endif @@ -497,13 +496,6 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint QCoreApplicationPrivate::~QCoreApplicationPrivate() { -#ifdef Q_OS_WASM - EM_ASM( - // unmount persistent directory as IDBFS - // see also QTBUG-70002 - FS.unmount('/home/web_user'); - ); -#endif #ifndef QT_NO_QOBJECT cleanupThreadData(); #endif @@ -795,17 +787,8 @@ void QCoreApplicationPrivate::init() Q_ASSERT_X(!QCoreApplication::self, "QCoreApplication", "there should be only one application object"); QCoreApplication::self = q; -#ifdef Q_OS_WASM - EM_ASM( - // mount and sync persistent filesystem to sandbox - FS.mount(IDBFS, {}, '/home/web_user'); - FS.syncfs(true, function(err) { - if (err) - Module.print(err); - }); - ); - #if QT_CONFIG(thread) +#ifdef Q_OS_WASM QThreadPrivate::idealThreadCount = emscripten::val::global("navigator")["hardwareConcurrency"].as(); #endif #endif diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 4bb25075212..f1d90f9caa2 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1715,13 +1715,7 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate() qt_gl_set_global_share_context(0); } #endif -#ifdef Q_OS_WASM - EM_ASM( - // unmount persistent directory as IDBFS - // see QTBUG-70002 - FS.unmount('/home/web_user'); - ); -#endif + platform_integration->destroy(); delete platform_theme;