summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2022-04-21 11:31:05 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2022-04-21 23:05:47 +0200
commitbead1894b7678f2563ea6b8fc443bb1c667fb489 (patch)
treed6390d6d9aac0420d364fd904bba5b6c62b075c5
parent37746d2f710957923427b25c028910d12860e008 (diff)
macOS: Reactivate current input context after discarding marked text
When composition is activate and the user switches from one window to another we get callbacks that the original window resigned key and the new window became key, which gets propagated as window activation events. QGuiApplication reacts to this by sending a QEvent::FocusAboutToChange event to the window that lost activation, which QWidgetWindow then responds to by committing the current input method. Unfortunately, at the time we get the key window callbacks from AppKit the keyWindow of NSApplication has already changed, so technically the QEvent::FocusAboutToChange event is too late and not in sync with the system state, manifesting in a bug in the input context and Text Services Manager (TSM) subsystem on macOS. In response to the commit of the input context we unmark (accept) the current composition, and then tell the NSTextInputContext of the focus view about this fact by calling discardMarkedText on it. But since the NSApp.keyWindow has already changed at this point, the focus view's input context is no longer the NSTextInputContext.currentInputContext, and as a result discardMarkedText will activate and deactivate the TSM document to ensure the right TSM document's marked text is discarded. This leaves things in an inconsistent state, as the current input context document, which was activated when the key window changed, is no longer active. We can work around this by manually calling activate on the original NSTextInputContext.currentInputContext. The documentation notes that this API should not be called directly, but unfortunately there are no other call sites in AppKit that end up in ActivateTSMDocument. A longer term fix would be to add plumbing to QWSI and QGuiApplication to allow notifying the application about the upcoming window activation before it happens, so that the FocusAboutToChange event and corresponding commit comes in at the right time (before the current input context has changed). Fixes: QTBUG-102083 Fixes: QTBUG-101278 Pick-to: 6.2 6.3 Change-Id: I8d369d1ca87cbb74a168ff3082bd0ab58eb391c5 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
-rw-r--r--src/plugins/platforms/cocoa/qcocoainputcontext.mm8
1 files changed, 8 insertions, 0 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm
index 63d23b0f43..7194da5433 100644
--- a/src/plugins/platforms/cocoa/qcocoainputcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm
@@ -118,7 +118,15 @@ void QCocoaInputContext::commit()
QMacAutoReleasePool pool;
[view unmarkText];
+
[view.inputContext discardMarkedText];
+ if (view.inputContext != NSTextInputContext.currentInputContext) {
+ // discardMarkedText will activate the TSM document of the given input context,
+ // which may not match the current input context. To ensure the current input
+ // context is not left in an inconsistent state with a deactivated document
+ // we need to manually activate it here.
+ [NSTextInputContext.currentInputContext activate];
+ }
}