diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2017-08-14 14:25:01 +0200 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2017-08-18 13:10:21 +0000 |
commit | 52ad5afe1c1d8f8d47fccbdf474f8c6119b94608 (patch) | |
tree | f7373601889f66af34f02c5cfaadfebfe800f05f /src/plugins/platforms/cocoa/qcocoabackingstore.mm | |
parent | dfdb94410a3b77381f20e426a2420065be9631f9 (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.mm | 53 |
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 ®ion, 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 |