diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 3b9d25fd3cb..3fbc06a089b 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -438,6 +438,24 @@ void QCocoaWindow::setVisible(bool visible) } } + // AppKit will in some cases set up the key view loop for child views, even if we + // don't set autorecalculatesKeyViewLoop, nor call recalculateKeyViewLoop ourselves. + // When a child window is promoted to a top level, AppKit will maintain the key view + // loop between the views, even if these views now cross NSWindows, even after we + // explicitly call recalculateKeyViewLoop. When the top level is then hidden, AppKit + // will complain when -[NSView _setHidden:setNeedsDisplay:] tries to transfer first + // responder by reading the nextValidKeyView, and it turns out to live in a different + // window. We mitigate this by a last second reset of the first responder, which is + // what AppKit also falls back to. It's unclear if the original situation of views + // having their nextKeyView pointing to views in other windows is kosher or not. + if (m_view.window.firstResponder == m_view && m_view.nextValidKeyView + && m_view.nextValidKeyView.window != m_view.window) { + qCDebug(lcQpaWindow) << "Detected nextValidKeyView" << m_view.nextValidKeyView + << "in different window" << m_view.nextValidKeyView.window + << "Resetting" << m_view.window << "first responder to nil."; + [m_view.window makeFirstResponder:nil]; + } + m_view.hidden = YES; if (parentCocoaWindow && window()->type() == Qt::Popup) {