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 <timur.pocheptsov@qt.io>
bb10
Tor Arne Vestbø 2021-08-31 23:48:45 +02:00
parent f8e0c7d008
commit ae8e96d4c2
1 changed files with 14 additions and 0 deletions

View File

@ -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)