From 7f72622c0f53a18b8e4215fc8428dc01894db938 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Thu, 21 Apr 2022 15:37:54 +0200 Subject: [PATCH] QIOSTextResponder: recreate responder upon reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apple introduced UITextInteraction in iOS 13, which caused issues with our text handling, and resulted in e00d888daefb. This, again, seems to be the reason why UIKit in some cases simply removes the input delegate from our text responder. This typically happens after a QPlatformInputContext::reset(), and then when the next character is typed on the input panel (and hence, leaves no informative stack trace). The result of removing the input delegate, which is the interface that let's Qt communicate IM changes back to UIKit, leads Qt and the UIKit out of IM sync. E.g for a japanese keyboard, after a QPlatformInputContext::reset(), the Qt input field would remove the marked text, but UIKit would still show japanese characters based on what used to be marked text. To work around this issue, this patch will therefore recreate the text responder when Qt tells us to reset. This will cause the first responder to change, which will apparently also reset the UIKit IM state. Fixes: QTBUG-102960 Pick-to: 6.3 6.2 5.15 Change-Id: I00901e980874fae819cc7d89a68fa34ae44808c2 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosinputcontext.mm | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index 1ae7f953b28..5aba4278c70 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -735,11 +735,24 @@ bool QIOSInputContext::inputMethodAccepted() const */ void QIOSInputContext::reset() { - qImDebug("updating Qt::ImQueryAll and unmarking text"); + qImDebug("releasing text responder"); + + // UIKit will sometimes, for unknown reasons, unset the input delegate on the + // current text responder. This seems to happen as a result of us calling + // [self.inputDelegate textDidChange:self] from [m_textResponder reset]. + // But it won't be set to nil directly, only after a character is typed on + // the input panel after the reset. This strange behavior seems to be related + // to us overriding [QUIView setInteraction] to ignore UITextInteraction. If we + // didn't do that, the delegate would be kept. But not overriding that function + // has its own share of issues, so it seems better to keep that way for now. + // Instead, we choose to recreate the text responder as a brute-force solution + // until we have better knowledge of what is going on (or implement the new + // UITextInteraction protocol). + [m_textResponder reset]; + [m_textResponder autorelease]; + m_textResponder = nullptr; update(Qt::ImQueryAll); - - [m_textResponder reset]; } /*!