summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa/qcocoabackingstore.mm
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2017-08-14 14:25:01 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2017-08-18 13:10:21 +0000
commit52ad5afe1c1d8f8d47fccbdf474f8c6119b94608 (patch)
treef7373601889f66af34f02c5cfaadfebfe800f05f /src/plugins/platforms/cocoa/qcocoabackingstore.mm
parentdfdb94410a3b77381f20e426a2420065be9631f9 (diff)
macOS: Redraw window bottom corners after synchronous backing store flush
Flushing outside of the display cycle does not care about any ordering between views, including the NSThemeFrame responsible for drawing the rounded corners of the window. Since Qt Widgets is doing a lot of synchronous flushing (for now, until we plumb update() to requestUpdate(), or enable layer-backing), we add a workaround that explicitly draws the corners after flushing, just like the logic in [NSView displayIfNeeded]. This is the same workaround used by WebKit: https://trac.webkit.org/changeset/85376/webkit Change-Id: I884152cdb2685569704e577b64b5ae278ed82c21 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoabackingstore.mm')
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm53
1 files changed, 52 insertions, 1 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index b6413485f2..b684435823 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -199,11 +199,62 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion &region, const QPo
if (shouldHandleViewLockManually)
[view unlockFocus];
- if (drawingOutsideOfDisplayCycle)
+ if (drawingOutsideOfDisplayCycle) {
+ redrawRoundedBottomCorners([view convertRect:region.boundingRect().toCGRect() toView:nil]);
[view.window flushWindow];
+ }
// FIXME: Tie to changing window flags and/or mask instead
[view invalidateWindowShadowIfNeeded];
}
+/*
+ When drawing outside of the display cycle, which Qt Widget does a lot,
+ we end up drawing over the NSThemeFrame, losing the rounded corners of
+ windows in the process.
+
+ To work around this, until we've enabled updates via setNeedsDisplay and/or
+ enabled layer-backed views, we ask the NSWindow to redraw the bottom corners
+ if they intersect with the flushed region.
+
+ This is the same logic used internally by e.g [NSView displayIfNeeded],
+ [NSRulerView _scrollToMatchContentView], and [NSClipView _immediateScrollToPoint:],
+ as well as the workaround used by WebKit to fix a similar bug:
+
+ https://trac.webkit.org/changeset/85376/webkit
+*/
+void QCocoaBackingStore::redrawRoundedBottomCorners(CGRect windowRect) const
+{
+#if !defined(QT_APPLE_NO_PRIVATE_APIS)
+ Q_ASSERT(this->window()->handle());
+ NSWindow *window = static_cast<QCocoaWindow *>(this->window()->handle())->nativeWindow();
+
+ static SEL intersectBottomCornersWithRect = NSSelectorFromString(
+ [NSString stringWithFormat:@"_%s%s:", "intersectBottomCorners", "WithRect"]);
+ if (NSMethodSignature *signature = [window methodSignatureForSelector:intersectBottomCornersWithRect]) {
+ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
+ invocation.target = window;
+ invocation.selector = intersectBottomCornersWithRect;
+ [invocation setArgument:&windowRect atIndex:2];
+ [invocation invoke];
+
+ NSRect cornerOverlap = NSZeroRect;
+ [invocation getReturnValue:&cornerOverlap];
+ if (!NSIsEmptyRect(cornerOverlap)) {
+ static SEL maskRoundedBottomCorners = NSSelectorFromString(
+ [NSString stringWithFormat:@"_%s%s:", "maskRounded", "BottomCorners"]);
+ if ((signature = [window methodSignatureForSelector:maskRoundedBottomCorners])) {
+ invocation = [NSInvocation invocationWithMethodSignature:signature];
+ invocation.target = window;
+ invocation.selector = maskRoundedBottomCorners;
+ [invocation setArgument:&cornerOverlap atIndex:2];
+ [invocation invoke];
+ }
+ }
+ }
+#else
+ Q_UNUSED(windowRect);
+#endif
+}
+
QT_END_NAMESPACE