summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/configure.json11
-rw-r--r--src/corelib/global/qrandom.cpp19
-rw-r--r--src/network/access/http2/http2protocol.cpp2
-rw-r--r--src/network/access/http2/http2protocol_p.h14
-rw-r--r--src/network/access/qhttp2protocolhandler.cpp31
-rw-r--r--src/network/access/qhttp2protocolhandler_p.h8
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm9
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm19
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm35
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm11
-rw-r--r--src/widgets/widgets/qmenu_mac.mm5
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 &region)
{
- 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 &region)
// 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();
}