diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2022-04-21 11:31:05 +0200 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2022-04-21 23:05:47 +0200 |
commit | bead1894b7678f2563ea6b8fc443bb1c667fb489 (patch) | |
tree | d6390d6d9aac0420d364fd904bba5b6c62b075c5 | |
parent | 37746d2f710957923427b25c028910d12860e008 (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.mm | 8 |
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]; + } } |