From ae8e96d4c2fc430ed6f71e422ef4aff2c7f15186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 31 Aug 2021 23:48:45 +0200 Subject: [PATCH] macOS: Don't rely on invalidateCursorRectsForView when mouse is over view Calling invalidateCursorRectsForView will normally result in a updateCursor callback, where we then set the current cursor using [NSCursor set]. But if an override cursor is set by AppKit, which happens for example when hovering over a resizable window's theme frame, then AppKit ignores the call to invalidateCursorRectsForView. And it will not consult the view when the override cursor is unset again, which results in the cursor being reset back to the default arrow cursor instead of the cursor that was set when we initiated the invalidateCursorRectsForView call. We need to hit-test to confirm that the mouse is over the view, as there might be child views in the mix that also have custom cursors, and we don't want to activate the parent view's cursor unless we're actually over that view. Fixes: QTBUG-81552 Fixes: QTBUG-96003 Pick-to: 6.2 5.15 Change-Id: I52573ab7be82f28c6a1cf686bd4b133551cfe98b Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoawindow.mm | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 6e7fc5cdbb..dcf65e9fa8 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1727,6 +1727,20 @@ void QCocoaWindow::setWindowCursor(NSCursor *cursor) view.cursor = cursor; [m_view.window invalidateCursorRectsForView:m_view]; + + // There's a bug in AppKit where calling invalidateCursorRectsForView when + // there's an override cursor active (for example when hovering over the + // window frame), will not result in a cursorUpdate: callback. To work around + // this we synthesize a cursor update event and call the callback ourselves, + // if we detect that the mouse is currently over the view. + auto locationInWindow = m_view.window.mouseLocationOutsideOfEventStream; + auto locationInSuperview = [m_view.superview convertPoint:locationInWindow fromView:nil]; + if ([m_view hitTest:locationInSuperview] == m_view) { + [m_view cursorUpdate:[NSEvent enterExitEventWithType:NSEventTypeCursorUpdate + location:locationInWindow modifierFlags:0 timestamp:0 + windowNumber:m_view.window.windowNumber context:nil + eventNumber:0 trackingNumber:0 userData:0]]; + } } void QCocoaWindow::registerTouch(bool enable)