diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/configure.json | 11 | ||||
-rw-r--r-- | src/corelib/global/qrandom.cpp | 19 | ||||
-rw-r--r-- | src/network/access/http2/http2protocol.cpp | 2 | ||||
-rw-r--r-- | src/network/access/http2/http2protocol_p.h | 14 | ||||
-rw-r--r-- | src/network/access/qhttp2protocolhandler.cpp | 31 | ||||
-rw-r--r-- | src/network/access/qhttp2protocolhandler_p.h | 8 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaglcontext.mm | 9 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaintegration.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaintegration.mm | 19 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 35 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.mm | 11 | ||||
-rw-r--r-- | src/widgets/widgets/qmenu_mac.mm | 5 |
13 files changed, 96 insertions, 71 deletions
diff --git a/src/corelib/configure.json b/src/corelib/configure.json index 51e6d1d391..8067ca70f1 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -459,11 +459,6 @@ "condition": "tests.cxx11_future", "output": [ "publicFeature" ] }, - "cxx11_random": { - "label": "C++11 <random>", - "condition": "tests.cxx11_random", - "output": [ "privateFeature" ] - }, "eventfd": { "label": "eventfd", "condition": "tests.eventfd", @@ -869,9 +864,9 @@ ensure that the IDEs they use either set QT_LOGGING_TO_CONSOLE to 1 or are able to read the logged output from journald, syslog or slog2." }, { - "type": "warning", - "condition": "!config.win32 && !config.darwin && !config.bsd && !features.cxx11_random", - "message": "No high-quality PRNG available for QRandomGenerator fallback.\nIf the HW or OS RNG fails, Qt will abort execution." + "type": "error", + "condition": "!tests.cxx11_random", + "message": "C++11 <random> is required and is missing or failed to compile." }, { "type": "error", diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index bafc312b3e..a7696719d1 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -46,16 +46,15 @@ #include <qthreadstorage.h> #include <private/qsimd_p.h> +#include <random> + #include <errno.h> #if QT_CONFIG(getentropy) # include <sys/random.h> -#else -# if QT_CONFIG(cxx11_random) -# include <random> -# include "qdeadlinetimer.h" -# include "qhashfunctions.h" -# endif +#elif !defined(Q_OS_BSD4) && !defined(Q_OS_WIN) +# include "qdeadlinetimer.h" +# include "qhashfunctions.h" # if QT_CONFIG(getauxval) # include <sys/auxv.h> @@ -258,7 +257,7 @@ static void fallback_fill(quint32 *ptr, qssize_t left) Q_DECL_NOTHROW // BSDs have arc4random(4) and these work even in chroot(2) arc4random_buf(ptr, left * sizeof(*ptr)); } -#elif QT_CONFIG(cxx11_random) +#else static QBasicAtomicInteger<unsigned> seed = Q_BASIC_ATOMIC_INITIALIZER(0U); static void fallback_update_seed(unsigned value) { @@ -343,12 +342,6 @@ static void fallback_fill(quint32 *ptr, qssize_t left) Q_DECL_NOTHROW fallback_update_seed(*ptr); } -#else -static void fallback_update_seed(unsigned) {} -static Q_NORETURN void fallback_fill(quint32 *, qssize_t) -{ - qFatal("Random number generator failed and no high-quality backup available"); -} #endif static qssize_t fill_cpu(quint32 *buffer, qssize_t count) Q_DECL_NOTHROW diff --git a/src/network/access/http2/http2protocol.cpp b/src/network/access/http2/http2protocol.cpp index 54811aeab0..bb3d6bf575 100644 --- a/src/network/access/http2/http2protocol.cpp +++ b/src/network/access/http2/http2protocol.cpp @@ -216,6 +216,8 @@ Frame default_SETTINGS_frame() // MAX frame size (16 kb), disable/enable PUSH_PROMISE builder.append(Settings::MAX_FRAME_SIZE_ID); builder.append(quint32(maxFrameSize)); + builder.append(Settings::INITIAL_WINDOW_SIZE_ID); + builder.append(initialStreamReceiveWindowSize); builder.append(Settings::ENABLE_PUSH_ID); builder.append(quint32(is_PUSH_PROMISE_enabled())); diff --git a/src/network/access/http2/http2protocol_p.h b/src/network/access/http2/http2protocol_p.h index b26ff0e9f4..c64e960002 100644 --- a/src/network/access/http2/http2protocol_p.h +++ b/src/network/access/http2/http2protocol_p.h @@ -129,10 +129,20 @@ enum Http2PredefinedParameters maxConcurrentStreams = 100 // HTTP/2, 6.5.2 }; -// It's int, it has internal linkage, it's ok to have it in headers - -// no ODR violation is possible. +// These are ints, const, they have internal linkage, it's ok to have them in +// headers - no ODR violation. const quint32 lastValidStreamID((quint32(1) << 31) - 1); // HTTP/2, 5.1.1 +// The default size of 64K is too small and limiting: if we use it, we end up +// sending WINDOW_UPDATE frames on a stream/session all the time, for each +// 2 DATE frames of size 16K (also default) we'll send a WINDOW_UPDATE frame +// for a given stream and have a download speed order of magnitude lower than +// our own HTTP/1.1 protocol handler. We choose a bigger window size (normally, +// HTTP/2 servers are not afraid to immediately set it to possible max anyway) +// and split this window size between our concurrent streams. +const qint32 initialSessionReceiveWindowSize = defaultSessionWindowSize * 10000; +const qint32 initialStreamReceiveWindowSize = initialSessionReceiveWindowSize / maxConcurrentStreams; + extern const Q_AUTOTEST_EXPORT char Http2clientPreface[clientPrefaceLength]; void prepare_for_protocol_upgrade(QHttpNetworkRequest &request); diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index a651fc4092..461f2429b3 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -161,8 +161,6 @@ bool sum_will_overflow(qint32 windowSize, qint32 delta) using namespace Http2; const std::deque<quint32>::size_type QHttp2ProtocolHandler::maxRecycledStreams = 10000; -const qint32 QHttp2ProtocolHandler::sessionMaxRecvWindowSize; -const qint32 QHttp2ProtocolHandler::streamInitialRecvWindowSize; const quint32 QHttp2ProtocolHandler::maxAcceptableTableSize; QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *channel) @@ -374,12 +372,10 @@ bool QHttp2ProtocolHandler::sendClientPreface() if (!frameWriter.write(*m_socket)) return false; - sessionRecvWindowSize = sessionMaxRecvWindowSize; - if (defaultSessionWindowSize < sessionMaxRecvWindowSize) { - const auto delta = sessionMaxRecvWindowSize - defaultSessionWindowSize; - if (!sendWINDOW_UPDATE(connectionStreamID, delta)) - return false; - } + sessionRecvWindowSize = Http2::initialSessionReceiveWindowSize; + const auto delta = Http2::initialSessionReceiveWindowSize - Http2::defaultSessionWindowSize; + if (!sendWINDOW_UPDATE(Http2::connectionStreamID, delta)) + return false; prefaceSent = true; waitingForSettingsACK = true; @@ -549,20 +545,20 @@ void QHttp2ProtocolHandler::handleDATA() if (inboundFrame.flags().testFlag(FrameFlag::END_STREAM)) { finishStream(stream); deleteActiveStream(stream.streamID); - } else if (stream.recvWindow < streamInitialRecvWindowSize / 2) { + } else if (stream.recvWindow < Http2::initialStreamReceiveWindowSize / 2) { QMetaObject::invokeMethod(this, "sendWINDOW_UPDATE", Qt::QueuedConnection, Q_ARG(quint32, stream.streamID), - Q_ARG(quint32, streamInitialRecvWindowSize - stream.recvWindow)); - stream.recvWindow = streamInitialRecvWindowSize; + Q_ARG(quint32, Http2::initialStreamReceiveWindowSize - stream.recvWindow)); + stream.recvWindow = Http2::initialStreamReceiveWindowSize; } } } - if (sessionRecvWindowSize < sessionMaxRecvWindowSize / 2) { + if (sessionRecvWindowSize < Http2::initialSessionReceiveWindowSize / 2) { QMetaObject::invokeMethod(this, "sendWINDOW_UPDATE", Qt::QueuedConnection, Q_ARG(quint32, connectionStreamID), - Q_ARG(quint32, sessionMaxRecvWindowSize - sessionRecvWindowSize)); - sessionRecvWindowSize = sessionMaxRecvWindowSize; + Q_ARG(quint32, Http2::initialSessionReceiveWindowSize - sessionRecvWindowSize)); + sessionRecvWindowSize = Http2::initialSessionReceiveWindowSize; } } @@ -1203,7 +1199,7 @@ quint32 QHttp2ProtocolHandler::createNewStream(const HttpMessagePair &message, b const Stream newStream(message, newStreamID, streamInitialSendWindowSize, - streamInitialRecvWindowSize); + Http2::initialStreamReceiveWindowSize); if (!uploadDone) { if (auto src = newStream.data()) { @@ -1398,7 +1394,8 @@ bool QHttp2ProtocolHandler::tryReserveStream(const Http2::Frame &pushPromiseFram promise.reservedID = reservedID; promise.pushHeader = requestHeader; - activeStreams.insert(reservedID, Stream(urlKey, reservedID, streamInitialRecvWindowSize)); + activeStreams.insert(reservedID, Stream(urlKey, reservedID, + Http2::initialStreamReceiveWindowSize)); return true; } @@ -1432,7 +1429,7 @@ void QHttp2ProtocolHandler::initReplyFromPushPromise(const HttpMessagePair &mess // Let's pretent we're sending a request now: Stream closedStream(message, promise.reservedID, streamInitialSendWindowSize, - streamInitialRecvWindowSize); + Http2::initialStreamReceiveWindowSize); closedStream.state = Stream::halfClosedLocal; activeStreams.insert(promise.reservedID, closedStream); promisedStream = &activeStreams[promise.reservedID]; diff --git a/src/network/access/qhttp2protocolhandler_p.h b/src/network/access/qhttp2protocolhandler_p.h index 82eea21818..b52f8ae10c 100644 --- a/src/network/access/qhttp2protocolhandler_p.h +++ b/src/network/access/qhttp2protocolhandler_p.h @@ -176,13 +176,9 @@ private: quint32 maxConcurrentStreams = Http2::maxConcurrentStreams; // Control flow: - static const qint32 sessionMaxRecvWindowSize = Http2::defaultSessionWindowSize * 10; - // Signed integer, it can become negative (it's still a valid window size): - qint32 sessionRecvWindowSize = sessionMaxRecvWindowSize; - // We do not negotiate this window size - // We have to send WINDOW_UPDATE frames to our peer also. - static const qint32 streamInitialRecvWindowSize = Http2::defaultSessionWindowSize; + // Signed integer, it can become negative (it's still a valid window size): + qint32 sessionRecvWindowSize = Http2::initialSessionReceiveWindowSize; // Updated by SETTINGS and WINDOW_UPDATE. qint32 sessionSendWindowSize = Http2::defaultSessionWindowSize; diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index 75ac348802..5ed81a7f1b 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -218,6 +218,9 @@ void QCocoaGLContext::windowWasHidden() void QCocoaGLContext::swapBuffers(QPlatformSurface *surface) { + if (surface->surface()->surfaceClass() == QSurface::Offscreen) + return; // Nothing to do + QWindow *window = static_cast<QCocoaWindow *>(surface)->window(); setActiveWindow(window); @@ -229,11 +232,13 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) Q_ASSERT(surface->surface()->supportsOpenGL()); QMacAutoReleasePool pool; + [m_context makeCurrentContext]; + + if (surface->surface()->surfaceClass() == QSurface::Offscreen) + return true; QWindow *window = static_cast<QCocoaWindow *>(surface)->window(); setActiveWindow(window); - - [m_context makeCurrentContext]; update(); return true; } diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index 8745b6a4e3..dc7c5916a3 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -77,6 +77,7 @@ public: bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const Q_DECL_OVERRIDE; + QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override; #ifndef QT_NO_OPENGL QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; #endif diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 61eeeaf436..dd17848109 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -56,6 +56,7 @@ #include <qpa/qplatforminputcontextfactory_p.h> #include <qpa/qplatformaccessibility.h> #include <qpa/qplatforminputcontextfactory_p.h> +#include <qpa/qplatformoffscreensurface.h> #include <QtCore/qcoreapplication.h> #include <QtGui/private/qcoregraphics_p.h> @@ -331,6 +332,24 @@ QPlatformWindow *QCocoaIntegration::createForeignWindow(QWindow *window, WId nat return new QCocoaWindow(window, nativeHandle); } +class QCocoaOffscreenSurface : public QPlatformOffscreenSurface +{ +public: + QCocoaOffscreenSurface(QOffscreenSurface *offscreenSurface) : QPlatformOffscreenSurface(offscreenSurface) {} + + QSurfaceFormat format() const override + { + Q_ASSERT(offscreenSurface()); + return offscreenSurface()->requestedFormat(); + } + bool isValid() const override { return true; } +}; + +QPlatformOffscreenSurface *QCocoaIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const +{ + return new QCocoaOffscreenSurface(surface); +} + #ifndef QT_NO_OPENGL QPlatformOpenGLContext *QCocoaIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 3230c32133..6fbe29f683 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -262,7 +262,7 @@ public: // for QNSView bool m_hasModalSession; bool m_frameStrutEventsEnabled; - bool m_isExposed; + QRect m_exposedRect; int m_registerTouchCount; bool m_resizableTransientParent; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 14aa127864..ed942af1b1 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -150,7 +150,6 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle) , m_needsInvalidateShadow(false) , m_hasModalSession(false) , m_frameStrutEventsEnabled(false) - , m_isExposed(false) , m_registerTouchCount(0) , m_resizableTransientParent(false) , m_alertRequest(NoAlertRequest) @@ -692,7 +691,7 @@ void QCocoaWindow::lower() bool QCocoaWindow::isExposed() const { - return m_isExposed; + return !m_exposedRect.isEmpty(); } bool QCocoaWindow::isOpaque() const @@ -1120,7 +1119,7 @@ void QCocoaWindow::handleGeometryChange() void QCocoaWindow::handleExposeEvent(const QRegion ®ion) { - const bool wasExposed = isExposed(); + const QRect previouslyExposedRect = m_exposedRect; // Ideally we'd implement isExposed() in terms of these properties, // plus the occlusionState of the NSWindow, and let the expose event @@ -1133,27 +1132,29 @@ void QCocoaWindow::handleExposeEvent(const QRegion ®ion) // a window being obscured is an empty region, and in the case of // a drawRect call is a non-null region, even if occlusionState // is still hidden. This ensures the window is prepared for display. - m_isExposed = m_view.window.visible - && m_view.window.screen - && !geometry().size().isEmpty() - && !region.isEmpty() - && !m_view.hiddenOrHasHiddenAncestor; + if (m_view.window.visible && m_view.window.screen + && !geometry().size().isEmpty() && !region.isEmpty() + && !m_view.hiddenOrHasHiddenAncestor) { + m_exposedRect = region.boundingRect(); + } else { + m_exposedRect = QRect(); + } QWindowPrivate *windowPrivate = qt_window_private(window()); if (windowPrivate->updateRequestPending) { // We can only deliver update request events when the window is exposed, - // and we also have to make sure we deliver the first expose event after - // becoming exposed as a real expose event, otherwise the exposed state - // of the QWindow is never updated. - // FIXME: Should this logic live in QGuiApplication? - if (wasExposed && m_isExposed) { + // and we also have to make sure we deliver any change to the exposed + // rect as a real expose event (including going from non-exposed to + // exposed). FIXME: Should this logic live in QGuiApplication? + if (isExposed() && m_exposedRect == previouslyExposedRect) { qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleExposeEvent" << window() << region << "as update request"; windowPrivate->deliverUpdateRequest(); return; + } else { + // Since updateRequestPending is still set, we will issue a deferred setNeedsDisplay + // from drawRect and get back into this code on the next display cycle, delivering + // the pending update request. } - - // FIXME: Should we re-trigger setNeedsDisplay in case of !wasExposed && m_isExposed? - // Or possibly send the expose event first, and then the update request? } qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleExposeEvent" << window() << region << "isExposed" << isExposed(); @@ -1240,7 +1241,7 @@ void QCocoaWindow::recreateWindowIfNeeded() if (m_windowModality != window()->modality()) recreateReason |= WindowModalityChanged; - const bool shouldBeContentView = !parentWindow && !m_viewIsEmbedded; + const bool shouldBeContentView = !parentWindow && !(m_viewIsToBeEmbedded || m_viewIsEmbedded); if (isContentView() != shouldBeContentView) recreateReason |= ContentViewChanged; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 054dca122f..9708aa4ce6 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -324,12 +324,13 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") m_platformWindow->handleExposeEvent(exposedRegion); - // A call to QWindow::requestUpdate was issued during the expose event, but - // AppKit will reset the needsDisplay state of the view after completing the - // current display cycle, so we need to defer the request to redisplay. - // FIXME: Perhaps this should be a trigger to enable CADisplayLink? if (qt_window_private(m_platformWindow->window())->updateRequestPending) { - qCDebug(lcQpaCocoaWindow) << "[QNSView drawRect:] deferring setNeedsDisplay"; + // A call to QWindow::requestUpdate was issued during the expose event, or we + // had to deliver a real expose event and still need to deliver the update. + // But AppKit will reset the needsDisplay state of the view after completing + // the current display cycle, so we need to defer the request to redisplay. + // FIXME: Perhaps this should be a trigger to enable CADisplayLink? + qCDebug(lcQpaCocoaWindow) << "[QNSView drawRect:] issuing deferred setNeedsDisplay due to pending update request"; dispatch_async(dispatch_get_main_queue (), ^{ [self setNeedsDisplay:YES]; }); diff --git a/src/widgets/widgets/qmenu_mac.mm b/src/widgets/widgets/qmenu_mac.mm index 7d932c670f..0d680fb4dc 100644 --- a/src/widgets/widgets/qmenu_mac.mm +++ b/src/widgets/widgets/qmenu_mac.mm @@ -135,6 +135,11 @@ void QMenuPrivate::moveWidgetToPlatformItem(QWidget *widget, QPlatformMenuItem* containerWindow->setFlags(wf | Qt::SubWindow); [(NSView *)widget->winId() setAutoresizingMask:NSViewWidthSizable]; + if (QPlatformNativeInterface::NativeResourceForIntegrationFunction function = resolvePlatformFunction("setEmbeddedInForeignView")) { + typedef void (*SetEmbeddedInForeignViewFunction)(QPlatformWindow *window, bool embedded); + reinterpret_cast<SetEmbeddedInForeignViewFunction>(function)(containerWindow->handle(), true); + } + item->setNativeContents((WId)containerView); container->show(); } |