summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2023-12-07 17:15:08 +0100
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2023-12-12 21:14:56 +0000
commitcf9b143cb3076a5d3ad8beec8ecf5175be925ae9 (patch)
tree707bf69dd5952e9dbbc94876136a5651417bc96d /src/plugins/platforms/cocoa
parentbf39bd8e06e9d66bfb9f01e83c743420e812b630 (diff)
macOS: Don't reset focus window to top level window when becoming key
The NSWindow becomes the "key window" when it's the window that currently receives keyboard events. This happens when switching activation between windows of the same app, or when the app is made active, restoring the key window status. Since the keyWindow property only applies to top level windows we were skipping child windows when processing the event callback, but we then proceeded to pass the top level window() to handleFocusWindowChanged, instead of the QWindow of the key window's first responder (the view that receives key input sent to the top level key window). To fix this, we let each platform window send its own focus change event, if it's the first responder, instead of relying on the top level window to send it on behalf of possible child windows. This decoupling ensures that we also send focus changes when we're not part of a view hierarchy Qt controls. Task-number: QTBUG-119287 Fixes: QTBUG-119054 Pick-to: 6.7 6.6 6.5 Change-Id: Iac06fe800291e243432335169c52db7685e173df Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/plugins/platforms/cocoa')
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm27
1 files changed, 18 insertions, 9 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 0533a6e1e9..e1714b104e 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -1246,19 +1246,21 @@ void QCocoaWindow::windowDidEndLiveResize()
void QCocoaWindow::windowDidBecomeKey()
{
- if (!isContentView())
- return;
-
if (isForeignWindow())
return;
- QNSView *firstResponderView = qt_objc_cast<QNSView *>(m_view.window.firstResponder);
- if (!firstResponderView)
+ // The NSWindow we're part of become key. Check if we're the first
+ // responder, and if so, deliver focus window change to our window.
+ if (m_view.window.firstResponder != m_view)
return;
- const QCocoaWindow *focusCocoaWindow = firstResponderView.platformWindow;
- if (focusCocoaWindow->windowIsPopupType())
+ qCDebug(lcQpaWindow) << m_view.window << "became key window."
+ << "Updating focus window to" << this;
+
+ if (windowIsPopupType()) {
+ qCDebug(lcQpaWindow) << "Window is popup. Skipping focus window change.";
return;
+ }
// See also [QNSView becomeFirstResponder]
QWindowSystemInterface::handleFocusWindowChanged<QWindowSystemInterface::SynchronousDelivery>(
@@ -1267,12 +1269,17 @@ void QCocoaWindow::windowDidBecomeKey()
void QCocoaWindow::windowDidResignKey()
{
- if (!isContentView())
+ if (isForeignWindow())
return;
- if (isForeignWindow())
+ // The NSWindow we're part of lost key. Check if we're the first
+ // responder, and if so, deliver window deactivation to our window.
+ if (m_view.window.firstResponder != m_view)
return;
+ qCDebug(lcQpaWindow) << m_view.window << "resigned key window."
+ << "Clearing focus window" << this;
+
// Make sure popups are closed before we deliver activation changes, which are
// otherwise ignored by QApplication.
closeAllPopups();
@@ -1283,6 +1290,8 @@ void QCocoaWindow::windowDidResignKey()
NSWindow *newKeyWindow = [NSApp keyWindow];
if (newKeyWindow && newKeyWindow != m_view.window
&& [newKeyWindow conformsToProtocol:@protocol(QNSWindowProtocol)]) {
+ qCDebug(lcQpaWindow) << "New key window" << newKeyWindow
+ << "is Qt window. Deferring focus window change.";
return;
}