From 6bc7309135ea6fc6c5d881e988b560e09825059d Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 23 Jul 2019 08:21:28 +0300 Subject: QResource: fix nullptr-check gone tautological Amends 136c5b9338f71775eb42528cfc7c23b2b4e5dff9. Before that change, each of the three members was a separate Q_GLOBAL_STATIC, so checking resourceList() for nullptr was the correct thing to do to find out whether the static was already destroyed. After the change, the resourceList() function will never return nullptr. Either resourceGlobalData.isDestroyed(), in which case dereferencing it asserts, or it isn't, in which case resourceList() returns a valid pointer. An explicit isDestroyed() check was added to the unregister function, but the register one was also checking resourceList() for nullptr, and this was left unprotected. Add the check and remove the now-tautological checks for nullptr resourceList(). Change-Id: I41fe66939ce858a77802b8af04c1de6e4fafe048 Reviewed-by: Edward Welbourne --- src/corelib/io/qresource.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 564a3e5f51..6c458da77a 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -852,8 +852,10 @@ bool QResourceRoot::mappingRootSubdir(const QString &path, QString *match) const Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree, const unsigned char *name, const unsigned char *data) { + if (resourceGlobalData.isDestroyed()) + return false; QMutexLocker lock(resourceMutex()); - if ((version == 0x01 || version == 0x2) && resourceList()) { + if (version == 0x01 || version == 0x2) { bool found = false; QResourceRoot res(version, tree, name, data); for(int i = 0; i < resourceList()->size(); ++i) { @@ -879,7 +881,7 @@ Q_CORE_EXPORT bool qUnregisterResourceData(int version, const unsigned char *tre return false; QMutexLocker lock(resourceMutex()); - if ((version == 0x01 || version == 0x02) && resourceList()) { + if (version == 0x01 || version == 0x02) { QResourceRoot res(version, tree, name, data); for(int i = 0; i < resourceList()->size(); ) { if(*resourceList()->at(i) == res) { -- cgit v1.2.3 From 698faf7b6de08bed2aa7e345982cedd907353e11 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Sat, 6 Jul 2019 12:30:00 +0300 Subject: Android: Fix SSL 1.1 support on API-21 OpenSSL 1.1.x libs must be suffixed otherwise it will use the system ones which on API-21 are OpenSSL 1.0 not 1.1 Fixes: QTBUG-76884 Change-Id: I7d4052be68cf7dc65f74a48da8e1e37182056a5e Reviewed-by: Volker Hilsheimer --- src/network/ssl/qsslsocket_openssl_symbols.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src') diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 483a2cbad0..c303e266ba 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -891,8 +891,25 @@ static QPair loadOpenSsl() // macOS's /usr/lib/libssl.dylib, /usr/lib/libcrypto.dylib will be picked up in the third // attempt, _after_ /Contents/Frameworks has been searched. // iOS does not ship a system libssl.dylib, libcrypto.dylib in the first place. +# if defined(Q_OS_ANDROID) + // OpenSSL 1.1.x must be suffixed otherwise it will use the system libcrypto.so libssl.so which on API-21 are OpenSSL 1.0 not 1.1 + auto openSSLSuffix = [](const QByteArray &defaultSuffix = {}) { + auto suffix = qgetenv("ANDROID_OPENSSL_SUFFIX"); + if (suffix.isEmpty()) + return defaultSuffix; + return suffix; + }; +# if QT_CONFIG(opensslv11) + static QString suffix = QString::fromLatin1(openSSLSuffix("_1_1")); +# else + static QString suffix = QString::fromLatin1(openSSLSuffix()); +# endif + libssl->setFileNameAndVersion(QLatin1String("ssl") + suffix, -1); + libcrypto->setFileNameAndVersion(QLatin1String("crypto") + suffix, -1); +# else libssl->setFileNameAndVersion(QLatin1String("ssl"), -1); libcrypto->setFileNameAndVersion(QLatin1String("crypto"), -1); +# endif if (libcrypto->load() && libssl->load()) { // libssl.so.0 and libcrypto.so.0 found return pair; -- cgit v1.2.3 From 5b3c09e35f71b5d848ee7554517d95deb9b577c7 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Fri, 26 Jul 2019 09:30:01 +0200 Subject: QMacStyle - another slider fix As a follow-up to fixed resize handling: the trick Gabriel wanted to use to enforce a specific look on a slider's bar, never actually worked due to misplaced statement which essentially is cancelling the 'magic' before the bar is drawn. Now it's fixed: bar is centered (between the rows of tickmarks above and below) + it's had a nice blue filling back! Change-Id: I3021c2b86e4c25981eeee015e32baa24ccebc3bd Reviewed-by: Volker Hilsheimer --- src/plugins/styles/mac/qmacstyle_mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 1d88d2c647..1ff1c22788 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -5362,10 +5362,10 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex const CGRect barRect = [cell barRectFlipped:hasTicks]; if (drawBar) { + [cell drawBarInside:barRect flipped:!verticalFlip]; // This ain't HIG kosher: force unfilled bar look. if (hasDoubleTicks) slider.numberOfTickMarks = numberOfTickMarks; - [cell drawBarInside:barRect flipped:!verticalFlip]; } if (hasTicks && drawTicks) { -- cgit v1.2.3 From e6498362fde937259295e9b2ddbe9b59136f47ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 25 Jul 2019 16:06:02 +0200 Subject: macOS: Respect color space set on NSWindow when flushing backingstore By default Qt tries to avoid potentially costly color matching by not assigning an sRGB color space to our backingstore, even if that's what we in practice fill it with. We used to do this by assigning the display's color space, which effectively opts out of color matching, similar to the old behavior of the device RGB color space (which nowadays implies sRGB). By picking up the color space from the NSWindow instead, we allow the user to override the color space to trigger color matching, for example by explicitly setting it to NSColorSpace.sRGBColorSpace. NSWindow will fall back to the screen's color space if the window doesn't have one set. Task-number: QTBUG-47660 Change-Id: Iac8177e85e86fe9044a41eb2c93fbf26bb83c248 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Timur Pocheptsov Reviewed-by: Simon Hausmann --- src/plugins/platforms/cocoa/qcocoabackingstore.h | 11 +++++++-- src/plugins/platforms/cocoa/qcocoabackingstore.mm | 30 ++++++++++++++--------- 2 files changed, 28 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index 2398e6351e..9be6814ae7 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -49,7 +49,14 @@ QT_BEGIN_NAMESPACE -class QNSWindowBackingStore : public QRasterBackingStore +class QCocoaBackingStore : public QRasterBackingStore +{ +protected: + QCocoaBackingStore(QWindow *window); + QCFType colorSpace() const; +}; + +class QNSWindowBackingStore : public QCocoaBackingStore { public: QNSWindowBackingStore(QWindow *window); @@ -64,7 +71,7 @@ private: void redrawRoundedBottomCorners(CGRect) const; }; -class QCALayerBackingStore : public QPlatformBackingStore +class QCALayerBackingStore : public QCocoaBackingStore { public: QCALayerBackingStore(QWindow *window); diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 78aa98094c..af50aabe15 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -48,11 +48,24 @@ QT_BEGIN_NAMESPACE -QNSWindowBackingStore::QNSWindowBackingStore(QWindow *window) +QCocoaBackingStore::QCocoaBackingStore(QWindow *window) : QRasterBackingStore(window) { } +QCFType QCocoaBackingStore::colorSpace() const +{ + NSView *view = static_cast(window()->handle())->view(); + return QCFType::constructFromGet(view.window.colorSpace.CGColorSpace); +} + +// ---------------------------------------------------------------------------- + +QNSWindowBackingStore::QNSWindowBackingStore(QWindow *window) + : QCocoaBackingStore(window) +{ +} + QNSWindowBackingStore::~QNSWindowBackingStore() { } @@ -175,11 +188,10 @@ void QNSWindowBackingStore::flush(QWindow *window, const QRegion ®ion, const Q_ASSERT_X(graphicsContext, "QCocoaBackingStore", "Focusing the view should give us a current graphics context"); - // Prevent potentially costly color conversion by assigning the display color space - // to the backingstore image. This does not copy the underlying image data. - CGColorSpaceRef displayColorSpace = view.window.screen.colorSpace.CGColorSpace; + // Tag backingstore image with color space based on the window. + // Note: This does not copy the underlying image data. QCFType cgImage = CGImageCreateCopyWithColorSpace( - QCFType(m_image.toCGImage()), displayColorSpace); + QCFType(m_image.toCGImage()), colorSpace()); // Create temporary image to use for blitting, without copying image data NSImage *backingStoreImage = [[[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize] autorelease]; @@ -305,7 +317,7 @@ template constexpr backwards_t backwards(R&& r) { return {std::forward(r)}; } QCALayerBackingStore::QCALayerBackingStore(QWindow *window) - : QPlatformBackingStore(window) + : QCocoaBackingStore(window) { qCDebug(lcQpaBackingStore) << "Creating QCALayerBackingStore for" << window; m_buffers.resize(1); @@ -444,11 +456,7 @@ bool QCALayerBackingStore::recreateBackBufferIfNeeded() << "based on requested" << m_requestedSize << "and dpr =" << devicePixelRatio; static auto pixelFormat = QImage::toPixelFormat(QImage::Format_ARGB32_Premultiplied); - - NSView *view = static_cast(window()->handle())->view(); - auto colorSpace = QCFType::constructFromGet(view.window.screen.colorSpace.CGColorSpace); - - m_buffers.back().reset(new GraphicsBuffer(requestedBufferSize, devicePixelRatio, pixelFormat, colorSpace)); + m_buffers.back().reset(new GraphicsBuffer(requestedBufferSize, devicePixelRatio, pixelFormat, colorSpace())); return true; } -- cgit v1.2.3 From e24a4976bebd7ca90deac2b40c08900625773a99 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Wed, 24 Jul 2019 15:05:23 +0200 Subject: QHostInfo: Always post results through the event loop to the receiver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lookups performed via QHostInfoRunnable must not synchronously call the user-code's receiver objects, as that would execute user-code in the wrong thread. Instead, post a metacall event through the event loop of the receiver object, or the thread that initiated the lookup. This was done correctly for the trivial cases of empty host name or cached results, so the code generally existed. By moving it from a global function into a member function of QHostInfoResult, we can simply access the required data to construct and post the event. As we process that posted event, we need to check that the context object (which is already guarded via QPointer) is still alive, if we had one in the first place. If we had one, and it's deleted, then abort. [ChangeLog][QtNetwork][QHostInfo] Functors used in the lookupHost overloads are now called correctly in the thread of the context object. When used without context object, the thread that initiates the lookup will run the functor, and is required to run an event loop. Change-Id: I9b38d4f9a23cfc4d9e07bc72de2d2cefe5d0d033 Fixes: QTBUG-76276 Reviewed-by: Edward Welbourne Reviewed-by: Mårten Nordheim --- src/network/kernel/qhostinfo.cpp | 50 ++++++++++++++++++++++++++++++++-------- src/network/kernel/qhostinfo_p.h | 9 +++++++- 2 files changed, 49 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 597c616fe9..7c82637564 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -106,11 +106,39 @@ int get_signal_index() return signal_index + QMetaObjectPrivate::signalOffset(senderMetaObject); } -void emit_results_ready(const QHostInfo &hostInfo, const QObject *receiver, - QtPrivate::QSlotObjectBase *slotObj) +} + +/* + The calling thread is likely the one that executes the lookup via + QHostInfoRunnable. Unless we operate with a queued connection already, + posts the QHostInfo to a dedicated QHostInfoResult object that lives in + the same thread as the user-provided receiver, or (if there is none) in + the thread that made the call to lookupHost. That QHostInfoResult object + then calls the user code in the correct thread. + + The 'result' object deletes itself (via deleteLater) when the metacall + event is received. +*/ +void QHostInfoResult::postResultsReady(const QHostInfo &info) { + // queued connection will take care of dispatching to right thread + if (!slotObj) { + emitResultsReady(info); + return; + } static const int signal_index = get_signal_index(); + + // we used to have a context object, but it's already destroyed + if (withContextObject && !receiver) + return; + + /* QHostInfoResult c'tor moves the result object to the thread of receiver. + If we don't have a receiver, then the result object will not live in a + thread that runs an event loop - so move it to this' thread, which is the thread + that initiated the lookup, and required to have a running event loop. */ auto result = new QHostInfoResult(receiver, slotObj); + if (!receiver) + result->moveToThread(thread()); Q_CHECK_PTR(result); const int nargs = 2; auto types = reinterpret_cast(malloc(nargs * sizeof(int))); @@ -120,15 +148,13 @@ void emit_results_ready(const QHostInfo &hostInfo, const QObject *receiver, auto args = reinterpret_cast(malloc(nargs * sizeof(void *))); Q_CHECK_PTR(args); args[0] = 0; - args[1] = QMetaType::create(types[1], &hostInfo); + args[1] = QMetaType::create(types[1], &info); Q_CHECK_PTR(args[1]); auto metaCallEvent = new QMetaCallEvent(slotObj, nullptr, signal_index, nargs, types, args); Q_CHECK_PTR(metaCallEvent); qApp->postEvent(result, metaCallEvent); } -} - /*! \class QHostInfo \brief The QHostInfo class provides static functions for host name lookups. @@ -335,6 +361,10 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, ready, the \a functor is called with a QHostInfo argument. The QHostInfo object can then be inspected to get the results of the lookup. + + The \a functor will be run in the thread that makes the call to lookupHost; + that thread must have a running Qt event loop. + \note There is no guarantee on the order the signals will be emitted if you start multiple requests with lookupHost(). @@ -632,7 +662,8 @@ int QHostInfo::lookupHostImpl(const QString &name, QHostInfo hostInfo(id); hostInfo.setError(QHostInfo::HostNotFound); hostInfo.setErrorString(QCoreApplication::translate("QHostInfo", "No host name given")); - emit_results_ready(hostInfo, receiver, slotObj); + QHostInfoResult result(receiver, slotObj); + result.postResultsReady(hostInfo); return id; } @@ -646,7 +677,8 @@ int QHostInfo::lookupHostImpl(const QString &name, QHostInfo info = manager->cache.get(name, &valid); if (valid) { info.setLookupId(id); - emit_results_ready(info, receiver, slotObj); + QHostInfoResult result(receiver, slotObj); + result.postResultsReady(info); return id; } } @@ -707,7 +739,7 @@ void QHostInfoRunnable::run() // signal emission hostInfo.setLookupId(id); - resultEmitter.emitResultsReady(hostInfo); + resultEmitter.postResultsReady(hostInfo); #if QT_CONFIG(thread) // now also iterate through the postponed ones @@ -720,7 +752,7 @@ void QHostInfoRunnable::run() QHostInfoRunnable* postponed = *it; // we can now emit hostInfo.setLookupId(postponed->id); - postponed->resultEmitter.emitResultsReady(hostInfo); + postponed->resultEmitter.postResultsReady(hostInfo); delete postponed; } manager->postponedLookups.erase(partitionBegin, partitionEnd); diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index 8898d6ff50..bbf4cc36d1 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -84,12 +84,14 @@ class QHostInfoResult : public QObject QPointer receiver = nullptr; QtPrivate::QSlotObjectBase *slotObj = nullptr; + const bool withContextObject = false; public: QHostInfoResult() = default; QHostInfoResult(const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj) : receiver(receiver), - slotObj(slotObj) + slotObj(slotObj), + withContextObject(slotObj && receiver) { connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &QObject::deleteLater); @@ -97,10 +99,15 @@ public: moveToThread(receiver->thread()); } + void postResultsReady(const QHostInfo &info); + public Q_SLOTS: inline void emitResultsReady(const QHostInfo &info) { if (slotObj) { + // we used to have a context object, but it's already destroyed + if (withContextObject && !receiver) + return; QHostInfo copy = info; void *args[2] = { 0, reinterpret_cast(©) }; slotObj->call(const_cast(receiver.data()), args); -- cgit v1.2.3 From 570fb55a334d77959ed158fc55ac66814bd33f15 Mon Sep 17 00:00:00 2001 From: Lorn Potter Date: Thu, 6 Jun 2019 16:47:18 +1000 Subject: wasm: fix wide character data download Need to pass correct buffer size Change-Id: I19cb65114f49decc225cd807d59f1f08ad6b70c9 Fixes: QTBUG-76212 Reviewed-by: Volker Hilsheimer --- src/network/access/qnetworkreplywasmimpl.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/network/access/qnetworkreplywasmimpl.cpp b/src/network/access/qnetworkreplywasmimpl.cpp index ee91dc20b3..53784407d8 100644 --- a/src/network/access/qnetworkreplywasmimpl.cpp +++ b/src/network/access/qnetworkreplywasmimpl.cpp @@ -135,8 +135,10 @@ static void q_loadCallback(val event) if (readyState == 4) { // done reply->setReplyAttributes(xhr["data-handler"].as(), status, statusText); - if (!responseString.isEmpty()) - reply->dataReceived(responseString.toUtf8(), responseString.size()); + if (!responseString.isEmpty()) { + QByteArray responseStringArray = responseString.toUtf8(); + reply->dataReceived(responseStringArray, responseStringArray.size()); + } } } if (status >= 400 && !statusText.isEmpty()) -- cgit v1.2.3 From 7138d6fd6bba2c2e55d02bccf7fd0c6c287eab29 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Mon, 22 Jul 2019 15:50:49 +0200 Subject: QWinRTFileEngine: Implement setSize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: QTBUG-77132 Change-Id: Ic0410297a2215f1b7b656966cbe84b925706532f Reviewed-by: André de la Rocha Reviewed-by: Maurice Kalinowski --- src/plugins/platforms/winrt/qwinrtfileengine.cpp | 23 +++++++++++++++++++++++ src/plugins/platforms/winrt/qwinrtfileengine.h | 1 + 2 files changed, 24 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp index 3014b30c38..e9b2a82763 100644 --- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp +++ b/src/plugins/platforms/winrt/qwinrtfileengine.cpp @@ -257,6 +257,29 @@ qint64 QWinRTFileEngine::size() const return qint64(size); } +bool QWinRTFileEngine::setSize(qint64 size) +{ + Q_D(QWinRTFileEngine); + if (!d->stream) { + setError(QFileDevice::ResizeError, QLatin1String("File must be open to be resized")); + return false; + } + + if (size < 0) { + setError(QFileDevice::ResizeError, QLatin1String("File size cannot be negative")); + return false; + } + + HRESULT hr = d->stream->put_Size(static_cast(size)); + RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ResizeError, false); + if (!flush()) { + setError(QFileDevice::ResizeError, QLatin1String("Could not flush file")); + return false; + } + + return true; +} + qint64 QWinRTFileEngine::pos() const { Q_D(const QWinRTFileEngine); diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.h b/src/plugins/platforms/winrt/qwinrtfileengine.h index 4485917c9e..453565a95a 100644 --- a/src/plugins/platforms/winrt/qwinrtfileengine.h +++ b/src/plugins/platforms/winrt/qwinrtfileengine.h @@ -79,6 +79,7 @@ public: bool close() override; bool flush() override; qint64 size() const override; + bool setSize(qint64 size) override; qint64 pos() const override; bool seek(qint64 pos) override; bool remove() override; -- cgit v1.2.3 From 3fbb6a957227968951283107813271218058b719 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 23 Jul 2019 07:48:46 +0200 Subject: QWinRTFileEngine: Handle QIODevice::Truncate when opening files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: QTBUG-77095 Change-Id: I45b38fab779518c49b22077c493d8640572d40d9 Reviewed-by: André de la Rocha Reviewed-by: Maurice Kalinowski --- src/plugins/platforms/winrt/qwinrtfileengine.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp index e9b2a82763..962e4ab938 100644 --- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp +++ b/src/plugins/platforms/winrt/qwinrtfileengine.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -196,7 +197,19 @@ bool QWinRTFileEngine::open(QIODevice::OpenMode openMode) hr = QWinRTFunctions::await(op, d->stream.GetAddressOf()); RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::OpenError, false); - d->openMode = openMode; + const ProcessOpenModeResult res = processOpenModeFlags(openMode); + if (!res.ok) { + setError(QFileDevice::OpenError, res.error); + return false; + } + d->openMode = res.openMode; + if (d->openMode & QIODevice::Truncate) { + if (!setSize(0)) { + close(); + setError(QFileDevice::OpenError, QLatin1String("Could not truncate file")); + return false; + } + } return SUCCEEDED(hr); } -- cgit v1.2.3 From 56b1cb0b040887c7f7a39561c1dc22c82af9ae7b Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 23 Jul 2019 11:10:59 +0200 Subject: Move processOpenModeFlags out of QFSFileEngine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The same logic is needed for QWinRTFileEngine. To be able to reuse the code, it was moved out of the class. Task-number: QTBUG-77095 Change-Id: If52b2fc8a0f3056d32fc693775565a1c3803b7d4 Reviewed-by: André de la Rocha Reviewed-by: Edward Welbourne --- src/corelib/io/qfsfileengine.cpp | 45 ++++++++++++++++++++++++++-------------- src/corelib/io/qfsfileengine_p.h | 10 ++++++--- 2 files changed, 36 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 387990ed79..5d3bef9e70 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -167,19 +167,21 @@ QFSFileEngine::QFSFileEngine(QFSFileEnginePrivate &dd) /*! \internal */ -bool QFSFileEngine::processOpenModeFlags(QIODevice::OpenMode *mode) +ProcessOpenModeResult processOpenModeFlags(QIODevice::OpenMode openMode) { - QIODevice::OpenMode &openMode = *mode; + ProcessOpenModeResult result; + result.ok = false; if ((openMode & QFile::NewOnly) && (openMode & QFile::ExistingOnly)) { qWarning("NewOnly and ExistingOnly are mutually exclusive"); - setError(QFile::OpenError, QLatin1String("NewOnly and ExistingOnly are mutually exclusive")); - return false; + result.error = QLatin1String("NewOnly and ExistingOnly are mutually exclusive"); + return result; } if ((openMode & QFile::ExistingOnly) && !(openMode & (QFile::ReadOnly | QFile::WriteOnly))) { qWarning("ExistingOnly must be specified alongside ReadOnly, WriteOnly, or ReadWrite"); - setError(QFile::OpenError, QLatin1String("ExistingOnly must be specified alongside ReadOnly, WriteOnly, or ReadWrite")); - return false; + result.error = QLatin1String( + "ExistingOnly must be specified alongside ReadOnly, WriteOnly, or ReadWrite"); + return result; } // Either Append or NewOnly implies WriteOnly @@ -190,7 +192,9 @@ bool QFSFileEngine::processOpenModeFlags(QIODevice::OpenMode *mode) if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append | QFile::NewOnly))) openMode |= QFile::Truncate; - return true; + result.ok = true; + result.openMode = openMode; + return result; } /*! @@ -234,16 +238,19 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode) return false; } - if (!processOpenModeFlags(&openMode)) + const ProcessOpenModeResult res = processOpenModeFlags(openMode); + if (!res.ok) { + setError(QFileDevice::OpenError, res.error); return false; + } - d->openMode = openMode; + d->openMode = res.openMode; d->lastFlushFailed = false; d->tried_stat = 0; d->fh = 0; d->fd = -1; - return d->nativeOpen(openMode); + return d->nativeOpen(d->openMode); } /*! @@ -262,17 +269,20 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh, QFile::FileHand Q_D(QFSFileEngine); - if (!processOpenModeFlags(&openMode)) + const ProcessOpenModeResult res = processOpenModeFlags(openMode); + if (!res.ok) { + setError(QFileDevice::OpenError, res.error); return false; + } - d->openMode = openMode; + d->openMode = res.openMode; d->lastFlushFailed = false; d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle); d->fileEntry.clear(); d->tried_stat = 0; d->fd = -1; - return d->openFh(openMode, fh); + return d->openFh(d->openMode, fh); } /*! @@ -321,10 +331,13 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd, QFile::FileHandle { Q_D(QFSFileEngine); - if (!processOpenModeFlags(&openMode)) + const ProcessOpenModeResult res = processOpenModeFlags(openMode); + if (!res.ok) { + setError(QFileDevice::OpenError, res.error); return false; + } - d->openMode = openMode; + d->openMode = res.openMode; d->lastFlushFailed = false; d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle); d->fileEntry.clear(); @@ -332,7 +345,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd, QFile::FileHandle d->fd = -1; d->tried_stat = 0; - return d->openFd(openMode, fd); + return d->openFd(d->openMode, fd); } diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 6b091a8eef..5231b4fe6f 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -61,6 +61,13 @@ QT_BEGIN_NAMESPACE +struct ProcessOpenModeResult { + bool ok; + QIODevice::OpenMode openMode; + QString error; +}; +inline Q_CORE_EXPORT ProcessOpenModeResult processOpenModeFlags(QIODevice::OpenMode mode); + class QFSFileEnginePrivate; class Q_CORE_EXPORT QFSFileEngine : public QAbstractFileEngine @@ -131,9 +138,6 @@ public: protected: QFSFileEngine(QFSFileEnginePrivate &dd); - -private: - inline bool processOpenModeFlags(QIODevice::OpenMode *mode); }; class Q_AUTOTEST_EXPORT QFSFileEnginePrivate : public QAbstractFileEnginePrivate -- cgit v1.2.3 From c8bb8cb7614768156f9cc4bccc2df928d5430067 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Fri, 26 Jul 2019 18:16:33 +0200 Subject: Windows QPA: Fix detection of the Surface Pen eraser button The Surface Pen eraser button generates Meta+F18/19/20 keystrokes, but when it is not touching the screen the Fn WM_KEYDOWN message is eaten and only a Fn WM_KEYUP message with the previous state as "not pressed" is generated, which would be ignored. With this patch we detect this case and synthesize the expected key events to allow the button to be used in applications. Fixes: QTBUG-77153 Change-Id: I075f5cbb903cb36c9ec241ee1bb31d436b725e3a Reviewed-by: Friedemann Kleint Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowskeymapper.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index c5af4d8042..da630005d6 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -1301,7 +1301,23 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg, || code == Qt::Key_Control || code == Qt::Key_Meta || code == Qt::Key_Alt)) { - // Someone ate the key down event + + // Workaround for QTBUG-77153: + // The Surface Pen eraser button generates Meta+F18/19/20 keystrokes, + // but when it is not touching the screen the Fn Down is eaten and only + // a Fn Up with the previous state as "not pressed" is generated, which + // would be ignored. We detect this case and synthesize the expected events. + if ((msg.lParam & 0x40000000) == 0 && + Qt::KeyboardModifier(state) == Qt::NoModifier && + ((code == Qt::Key_F18) || (code == Qt::Key_F19) || (code == Qt::Key_F20))) { + QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyPress, code, + Qt::MetaModifier, scancode, + quint32(msg.wParam), MetaLeft); + QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyRelease, code, + Qt::NoModifier, scancode, + quint32(msg.wParam), 0); + result = true; + } } else { if (!code) code = asciiToKeycode(rec->ascii ? char(rec->ascii) : char(msg.wParam), state); -- cgit v1.2.3 From f4647b40ca9319508468ead8144116d0a5718ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 29 Jul 2019 15:13:02 +0200 Subject: macOS: Respect QSurfaceFormat color space when creating NSWindow Task-number: QTBUG-47660 Change-Id: I90a2956bfaa52c361a3eba32f0ea19c0eca8c277 Reviewed-by: Simon Hausmann --- src/plugins/platforms/cocoa/qcocoawindow.mm | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 42b662cfe4..b609fb3995 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1647,6 +1647,9 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel) [nsWindow setDepthLimit:NSWindowDepthTwentyfourBitRGB]; } + if (format().colorSpace() == QSurfaceFormat::sRGBColorSpace) + nsWindow.colorSpace = NSColorSpace.sRGBColorSpace; + return nsWindow; } -- cgit v1.2.3 From 3e7463411e549100eee7abe2a8fae16fd965f8f6 Mon Sep 17 00:00:00 2001 From: David Faure Date: Mon, 29 Jul 2019 14:27:16 +0200 Subject: Fix crash when the focus widget gets a focus proxy after the fact QApplicationPrivate::focus_widget became a dangling pointer in the following scenario: A widget first gets focus and later on gets a focus proxy. QApplicationPrivate::focus_widget was still pointing to the initial widget. Upon destruction, QWidget::hasFocus() [which follows to the focus proxy and then compares with focus_widget] was therefore false for both widgets. So QWidget::clearFocus() didn't call QApplicationPrivate::setFocusWidget(0) for either of them. As a result, focus_widget remained set, and became dangling. In real life, this happened with a QWebEngineView, which the application gave focus to upon creation. At that time it doesn't have a focus proxy yet. That happens later, in QWebEngineViewPrivate::widgetChanged. https://bugs.kde.org/show_bug.cgi?id=381793 Change-Id: Ifee610bb76a2d4d2797b98ece9bffe5fffe3c6a6 Reviewed-by: Volker Hilsheimer --- src/widgets/kernel/qwidget.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 353a80d1c5..04290a4ce1 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -6436,8 +6436,18 @@ void QWidget::setFocusProxy(QWidget * w) } } + QWidget *oldDeepestFocusProxy = d_func()->deepestFocusProxy(); + if (!oldDeepestFocusProxy) + oldDeepestFocusProxy = this; + const bool changingAppFocusWidget = (QApplicationPrivate::focus_widget == oldDeepestFocusProxy); + d->createExtra(); d->extra->focus_proxy = w; + + if (changingAppFocusWidget) { + QWidget *newDeepestFocusProxy = d_func()->deepestFocusProxy(); + QApplicationPrivate::focus_widget = newDeepestFocusProxy ? newDeepestFocusProxy : this; + } } -- cgit v1.2.3