summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-10-01 01:01:20 +0200
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-10-01 11:47:42 +0200
commit8791a8398ac232a8daab98601f1bef88bdf7638f (patch)
tree4be3c8daaff311943215f399ae7300ca4af4f969 /src/plugins
parent56f084781e2b8891929eca0070212fd7a32b32fc (diff)
parent4e40c54a3caabb6bced27e18e040ee88b739a3c8 (diff)
Merge "Merge remote-tracking branch 'origin/5.14' into 5.15"
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/android/qandroidplatformtheme.cpp5
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm2
-rw-r--r--src/plugins/platforms/cocoa/qnsview_drawing.mm205
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp62
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h3
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp12
6 files changed, 191 insertions, 98 deletions
diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp
index 7fc68c3d7c..d3a8a53241 100644
--- a/src/plugins/platforms/android/qandroidplatformtheme.cpp
+++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp
@@ -465,7 +465,8 @@ QVariant QAndroidPlatformTheme::themeHint(ThemeHint hint) const
return QStringList(QLatin1String("android"));
}
return QStringList(QLatin1String("fusion"));
-
+ case DialogButtonBoxLayout:
+ return QVariant(QPlatformDialogHelper::AndroidLayout);
case MouseDoubleClickDistance:
{
int minimumDistance = qEnvironmentVariableIntValue("QT_ANDROID_MINIMUM_MOUSE_DOUBLE_CLICK_DISTANCE");
@@ -489,8 +490,6 @@ QVariant QAndroidPlatformTheme::themeHint(ThemeHint hint) const
Q_FALLTHROUGH();
}
- case DialogButtonBoxLayout:
- return QVariant(QPlatformDialogHelper::AndroidLayout);
default:
return QPlatformTheme::themeHint(hint);
}
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index d3bb0711f0..e87fc39c42 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -881,7 +881,7 @@ void QCocoaEventDispatcherPrivate::processPostedEvents()
return;
}
- int serial = serialNumber.load();
+ int serial = serialNumber.loadRelaxed();
if (!threadData->canWait || (serial != lastSerial)) {
lastSerial = serial;
QCoreApplication::sendPostedEvents();
diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm
index e72142466b..ce5488ead0 100644
--- a/src/plugins/platforms/cocoa/qnsview_drawing.mm
+++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm
@@ -43,9 +43,7 @@
- (void)initDrawing
{
- self.wantsLayer = [self layerExplicitlyRequested]
- || [self shouldUseMetalLayer]
- || [self layerEnabledByMacOS];
+ [self updateLayerBacking];
// Enable high-DPI OpenGL for retina displays. Enabling has the side
// effect that Cocoa will start calling glViewport(0, 0, width, height),
@@ -71,22 +69,13 @@
return YES;
}
-- (void)drawRect:(NSRect)dirtyRect
-{
- Q_UNUSED(dirtyRect);
-
- if (!m_platformWindow)
- return;
-
- QRegion exposedRegion;
- const NSRect *dirtyRects;
- NSInteger numDirtyRects;
- [self getRectsBeingDrawn:&dirtyRects count:&numDirtyRects];
- for (int i = 0; i < numDirtyRects; ++i)
- exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect();
+// ----------------------- Layer setup -----------------------
- qCDebug(lcQpaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion;
- m_platformWindow->handleExposeEvent(exposedRegion);
+- (void)updateLayerBacking
+{
+ self.wantsLayer = [self layerEnabledByMacOS]
+ || [self layerExplicitlyRequested]
+ || [self shouldUseMetalLayer];
}
- (BOOL)layerEnabledByMacOS
@@ -123,40 +112,81 @@
return surfaceType == QWindow::MetalSurface || surfaceType == QWindow::VulkanSurface;
}
+/*
+ This method is called by AppKit when layer-backing is requested by
+ setting wantsLayer too YES (via -[NSView _updateLayerBackedness]),
+ or in cases where AppKit itself decides that a view should be
+ layer-backed.
+
+ Note however that some code paths in AppKit will not go via this
+ method for creating the backing layer, and will instead create the
+ layer manually, and just call setLayer. An example of this is when
+ an NSOpenGLContext is attached to a view, in which case AppKit will
+ create a new layer in NSOpenGLContextSetLayerOnViewIfNecessary.
+
+ For this reason we leave the implementation of this override as
+ minimal as possible, only focusing on creating the appropriate
+ layer type, and then leave it up to setLayer to do the work of
+ making sure the layer is set up correctly.
+*/
- (CALayer *)makeBackingLayer
{
if ([self shouldUseMetalLayer]) {
// Check if Metal is supported. If it isn't then it's most likely
// too late at this point and the QWindow will be non-functional,
// but we can at least print a warning.
- if (![MTLCreateSystemDefaultDevice() autorelease]) {
- qWarning() << "QWindow initialization error: Metal is not supported";
- return [super makeBackingLayer];
+ if ([MTLCreateSystemDefaultDevice() autorelease]) {
+ return [CAMetalLayer layer];
+ } else {
+ qCWarning(lcQpaDrawing) << "Failed to create QWindow::MetalSurface."
+ << "Metal is not supported by any of the GPUs in this system.";
}
-
- CAMetalLayer *layer = [CAMetalLayer layer];
-
- // Set the contentsScale for the layer. This is normally done in
- // viewDidChangeBackingProperties, however on startup that function
- // is called before the layer is created here. The layer's drawableSize
- // is updated from layoutSublayersOfLayer as usual.
- layer.contentsScale = self.window.backingScaleFactor;
-
- return layer;
}
return [super makeBackingLayer];
}
+/*
+ This method is called by AppKit whenever the view is asked to change
+ its layer, which can happen both as a result of enabling layer-backing,
+ or when a layer is set explicitly. The latter can happen both when a
+ view is layer-hosting, or when AppKit internals are switching out the
+ layer-backed view, as described above for makeBackingLayer.
+*/
- (void)setLayer:(CALayer *)layer
{
- qCDebug(lcQpaDrawing) << "Making" << self << "layer-backed with" << layer
- << "due to being" << ([self layerExplicitlyRequested] ? "explicitly requested"
+ qCDebug(lcQpaDrawing) << "Making" << self
+ << (self.wantsLayer ? "layer-backed" : "layer-hosted")
+ << "with" << layer << "due to being" << ([self layerExplicitlyRequested] ? "explicitly requested"
: [self shouldUseMetalLayer] ? "needed by surface type" : "enabled by macOS");
+
+ if (layer.delegate && layer.delegate != self) {
+ qCWarning(lcQpaDrawing) << "Layer already has delegate" << layer.delegate
+ << "This delegate is responsible for all view updates for" << self;
+ } else {
+ layer.delegate = self;
+ }
+
[super setLayer:layer];
- layer.delegate = self;
+
+ // When adding a view to a view hierarchy the backing properties will change
+ // which results in updating the contents scale, but in case of switching the
+ // layer on a view that's already in a view hierarchy we need to manually ensure
+ // the scale is up to date.
+ if (self.superview)
+ [self updateLayerContentsScale];
+
+ if (self.opaque && lcQpaDrawing().isDebugEnabled()) {
+ // If the view claims to be opaque we expect it to fill the entire
+ // layer with content, in which case we want to detect any areas
+ // where it doesn't.
+ layer.backgroundColor = NSColor.magentaColor.CGColor;
+ }
+
}
+// ----------------------- Layer updates -----------------------
+
- (NSViewLayerContentsRedrawPolicy)layerContentsRedrawPolicy
{
// We need to set this explicitly since the super implementation
@@ -164,17 +194,95 @@
return NSViewLayerContentsRedrawDuringViewResize;
}
-#if 0 // Disabled until we enable lazy backingstore resizing
- (NSViewLayerContentsPlacement)layerContentsPlacement
{
- // Always place the layer at top left without any automatic scaling,
- // so that we can re-use larger layers when resizing a window down.
+ // Always place the layer at top left without any automatic scaling.
+ // This will highlight situations where we're missing content for the
+ // layer by not responding to the displayLayer: request synchronously.
+ // It also allows us to re-use larger layers when resizing a window down.
return NSViewLayerContentsPlacementTopLeft;
}
-#endif
+- (void)viewDidChangeBackingProperties
+{
+ qCDebug(lcQpaDrawing) << "Backing properties changed for" << self;
+
+ if (self.layer)
+ [self updateLayerContentsScale];
+
+ // Ideally we would plumb this situation through QPA in a way that lets
+ // clients invalidate their own caches, recreate QBackingStore, etc.
+ // For now we trigger an expose, and let QCocoaBackingStore deal with
+ // buffer invalidation internally.
+ [self setNeedsDisplay:YES];
+}
+
+- (void)updateLayerContentsScale
+{
+ // We expect clients to fill the layer with retina aware content,
+ // based on the devicePixelRatio of the QWindow, so we set the
+ // layer's content scale to match that. By going via devicePixelRatio
+ // instead of applying the NSWindow's backingScaleFactor, we also take
+ // into account OpenGL views with wantsBestResolutionOpenGLSurface set
+ // to NO. In this case the window will have a backingScaleFactor of 2,
+ // but the QWindow will have a devicePixelRatio of 1.
+ auto devicePixelRatio = m_platformWindow->devicePixelRatio();
+ qCDebug(lcQpaDrawing) << "Updating" << self.layer << "content scale to" << devicePixelRatio;
+ self.layer.contentsScale = devicePixelRatio;
+}
+
+/*
+ This method is called by AppKit to determine whether it should update
+ the contentScale of the layer to match the window backing scale.
+
+ We always return NO since we're updating the contents scale manually.
+*/
+- (BOOL)layer:(CALayer *)layer shouldInheritContentsScale:(CGFloat)scale fromWindow:(NSWindow *)window
+{
+ Q_UNUSED(layer); Q_UNUSED(scale); Q_UNUSED(window);
+ return NO;
+}
+
+// ----------------------- Draw callbacks -----------------------
+
+/*
+ This method is called by AppKit for the non-layer case, where we are
+ drawing into the NSWindow's surface.
+*/
+- (void)drawRect:(NSRect)dirtyBoundingRect
+{
+ Q_ASSERT_X(!self.layer, "QNSView",
+ "The drawRect code path should not be hit when we are layer backed");
+
+ if (!m_platformWindow)
+ return;
+
+ QRegion exposedRegion;
+ const NSRect *dirtyRects;
+ NSInteger numDirtyRects;
+ [self getRectsBeingDrawn:&dirtyRects count:&numDirtyRects];
+ for (int i = 0; i < numDirtyRects; ++i)
+ exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect();
+
+ if (exposedRegion.isEmpty())
+ exposedRegion = QRectF::fromCGRect(dirtyBoundingRect).toRect();
+
+ qCDebug(lcQpaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion;
+ m_platformWindow->handleExposeEvent(exposedRegion);
+}
+
+/*
+ This method is called by AppKit when we are layer-backed, where
+ we are drawing into the layer.
+*/
- (void)displayLayer:(CALayer *)layer
{
+ Q_ASSERT_X(self.layer && layer == self.layer, "QNSView",
+ "The displayLayer code path should only be hit for our own layer");
+
+ if (!m_platformWindow)
+ return;
+
if (!NSThread.isMainThread) {
// Qt is calling AppKit APIs such as -[NSOpenGLContext setView:] on secondary threads,
// which we shouldn't do. This may result in AppKit (wrongly) triggering a display on
@@ -184,29 +292,8 @@
return;
}
- Q_ASSERT(layer == self.layer);
-
- if (!m_platformWindow)
- return;
-
qCDebug(lcQpaDrawing) << "[QNSView displayLayer]" << m_platformWindow->window();
-
- // FIXME: Find out if there's a way to resolve the dirty rect like in drawRect:
m_platformWindow->handleExposeEvent(QRectF::fromCGRect(self.bounds).toRect());
}
-- (void)viewDidChangeBackingProperties
-{
- qCDebug(lcQpaDrawing) << "Backing properties changed for" << self;
-
- if (self.layer)
- self.layer.contentsScale = self.window.backingScaleFactor;
-
- // Ideally we would plumb this situation through QPA in a way that lets
- // clients invalidate their own caches, recreate QBackingStore, etc.
- // For now we trigger an expose, and let QCocoaBackingStore deal with
- // buffer invalidation internally.
- [self setNeedsDisplay:YES];
-}
-
@end
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index 64b83e2bc4..f2d31d5783 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -891,13 +891,6 @@ QWindowsOpenGLContextFormat QWindowsOpenGLContextFormat::current()
result.profile = QSurfaceFormat::CoreProfile;
else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
result.profile = QSurfaceFormat::CompatibilityProfile;
- if (result.version < 0x0400)
- return result;
- // v4.0 onwards
- value = 0;
- QOpenGLStaticContext::opengl32.glGetIntegerv(RESET_NOTIFICATION_STRATEGY_ARB, &value);
- if (value == LOSE_CONTEXT_ON_RESET_ARB)
- result.options |= QSurfaceFormat::ResetNotification;
return result;
}
@@ -975,6 +968,7 @@ QOpenGLTemporaryContext::~QOpenGLTemporaryContext()
*/
#define SAMPLE_BUFFER_EXTENSION "GL_ARB_multisample"
+#define ROBUSTNESS_EXTENSION "GL_ARB_robustness"
QOpenGLStaticContext::QOpenGLStaticContext() :
vendor(QOpenGLStaticContext::getGlString(GL_VENDOR)),
@@ -995,9 +989,31 @@ QOpenGLStaticContext::QOpenGLStaticContext() :
wglGetExtensionsStringARB(reinterpret_cast<WglGetExtensionsStringARB>(
reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetExtensionsStringARB"))))
{
- if (extensionNames.startsWith(SAMPLE_BUFFER_EXTENSION " ")
- || extensionNames.indexOf(" " SAMPLE_BUFFER_EXTENSION " ") != -1)
- extensions |= SampleBuffers;
+ if (defaultFormat.version < 0x0300) {
+ if (extensionNames.startsWith(SAMPLE_BUFFER_EXTENSION " ")
+ || extensionNames.indexOf(" " SAMPLE_BUFFER_EXTENSION " ") != -1)
+ extensions |= SampleBuffers;
+ if (extensionNames.startsWith(ROBUSTNESS_EXTENSION " ")
+ || extensionNames.indexOf(" " ROBUSTNESS_EXTENSION " ") != -1)
+ extensions |= Robustness;
+ } else {
+ typedef const GLubyte * (APIENTRY *glGetStringi_t)(GLenum, GLuint);
+ auto glGetStringi = reinterpret_cast<glGetStringi_t>(
+ reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("glGetStringi")));
+ if (glGetStringi) {
+ GLint n = 0;
+ QOpenGLStaticContext::opengl32.glGetIntegerv(GL_NUM_EXTENSIONS, &n);
+ for (GLint i = 0; i < n; ++i) {
+ const char *p = reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, i));
+ if (p) {
+ if (!strcmp(p, SAMPLE_BUFFER_EXTENSION))
+ extensions |= SampleBuffers;
+ else if (!strcmp(p, ROBUSTNESS_EXTENSION))
+ extensions |= Robustness;
+ }
+ }
+ }
+ }
}
QByteArray QOpenGLStaticContext::getGlString(unsigned int which)
@@ -1236,27 +1252,11 @@ bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval)
if (m_staticContext->wglGetSwapInternalExt && obtainedSwapInterval)
*obtainedSwapInterval = m_staticContext->wglGetSwapInternalExt();
- bool hasRobustness = false;
- if (m_obtainedFormat.majorVersion() < 3) {
- const char *exts = reinterpret_cast<const char *>(QOpenGLStaticContext::opengl32.glGetString(GL_EXTENSIONS));
- hasRobustness = exts && strstr(exts, "GL_ARB_robustness");
- } else {
- typedef const GLubyte * (APIENTRY *glGetStringi_t)(GLenum, GLuint);
- auto glGetStringi = reinterpret_cast<glGetStringi_t>(
- reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("glGetStringi")));
- if (glGetStringi) {
- GLint n = 0;
- QOpenGLStaticContext::opengl32.glGetIntegerv(GL_NUM_EXTENSIONS, &n);
- for (GLint i = 0; i < n; ++i) {
- const char *p = reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, i));
- if (p && !strcmp(p, "GL_ARB_robustness")) {
- hasRobustness = true;
- break;
- }
- }
- }
- }
- if (hasRobustness) {
+ if (testFlag(m_staticContext->extensions, QOpenGLStaticContext::Robustness)) {
+ GLint value = 0;
+ QOpenGLStaticContext::opengl32.glGetIntegerv(RESET_NOTIFICATION_STRATEGY_ARB, &value);
+ if (value == LOSE_CONTEXT_ON_RESET_ARB)
+ m_obtainedFormat.setOption(QSurfaceFormat::ResetNotification);
m_getGraphicsResetStatus = reinterpret_cast<GlGetGraphicsResetStatusArbType>(
reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("glGetGraphicsResetStatusARB")));
}
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h
index e962af39c2..e5f6fefd5a 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsglcontext.h
@@ -142,7 +142,8 @@ public:
enum Extensions
{
SampleBuffers = 0x1,
- sRGBCapableFramebuffer = 0x2
+ sRGBCapableFramebuffer = 0x2,
+ Robustness = 0x4,
};
typedef bool
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index ffc8f5ed21..a4f4099aa6 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -2697,10 +2697,16 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re
return true;
}
if (localPos.y() < 0) {
- const int topResizeBarPos = -frameMargins().top();
- if (localPos.y() >= topResizeBarPos)
+ // We want to return HTCAPTION/true only over the outer sizing frame, not the entire title bar,
+ // otherwise the title bar buttons (close, etc.) become unresponsive on Windows 7 (QTBUG-78262).
+ // However, neither frameMargins() nor GetSystemMetrics(SM_CYSIZEFRAME), etc., give the correct
+ // sizing frame height in all Windows versions/scales. This empirical constant seems to work, though.
+ const int sizingHeight = 9;
+ const int topResizeBarPos = sizingHeight - frameMargins().top();
+ if (localPos.y() < topResizeBarPos) {
*result = HTCAPTION; // Extend caption over top resize bar, let's user move the window.
- return true;
+ return true;
+ }
}
}
if (fixedWidth && (localPos.x() < 0 || localPos.x() >= size.width())) {