QIOSInputContext: use QIOSResponder when the focus object is Qt::ImReadOnly

In Qt, Qt::ImEnabled means that the focus object accepts text input from
input method (IM) events. But the IM API also contains API for dealing
with text selections. Text input and text selections are logically two
different operations, but since IM makes use of selections to implement
text input (like selecting a word to suggest a spelling correction), it's
understandable that they are combined into to same API.

So when a focus object reports Qt::ImEnabled to be false, it only means
that it doesn't accept input. E.g a TextArea in QML with "readOnly:true"
will set Qt::ImEnabled to false. At the same time, it can have
"selectByMouse:true", which lets you select text with the mouse.
This behavior is consistent in Qt, for both Quick, Controls 2 and Widgets.

Since we want to support any selections done in controls/widgets on iOS
with selection handles and edit menus, regardless if the focus object
accepts input or not, this patch will set the QIOSResponder (with read-only
actions) as first responder when we detect a focus object with Qt::ImReadOnly.
This means that if a query for Qt::ImReadOnly returns "true", we take that
to mean that it implements the IM API, but without accepting input.

Task-number: QTBUG-91545
Change-Id: I07349909a3bca81f484a2e9af9672428dca62c49
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Richard Moe Gustavsen 2021-10-25 13:57:47 +02:00
parent 2211092aa5
commit aae4d52cbb

View File

@ -675,16 +675,23 @@ void QIOSInputContext::update(Qt::InputMethodQueries updatedProperties)
} }
// Mask for properties that we are interested in and see if any of them changed // Mask for properties that we are interested in and see if any of them changed
updatedProperties &= (Qt::ImEnabled | Qt::ImHints | Qt::ImQueryInput | Qt::ImEnterKeyType | Qt::ImPlatformData); updatedProperties &= (Qt::ImEnabled | Qt::ImHints | Qt::ImQueryInput | Qt::ImEnterKeyType | Qt::ImPlatformData | Qt::ImReadOnly);
// Perform update first, so we can trust the value of inputMethodAccepted() // Perform update first, so we can trust the value of inputMethodAccepted()
Qt::InputMethodQueries changedProperties = m_imeState.update(updatedProperties); Qt::InputMethodQueries changedProperties = m_imeState.update(updatedProperties);
if (inputMethodAccepted()) { const bool inputIsReadOnly = m_imeState.currentState.value(Qt::ImReadOnly).toBool();
if (inputMethodAccepted() || inputIsReadOnly) {
if (!m_textResponder || [m_textResponder needsKeyboardReconfigure:changedProperties]) { if (!m_textResponder || [m_textResponder needsKeyboardReconfigure:changedProperties]) {
qImDebug("creating new text responder");
[m_textResponder autorelease]; [m_textResponder autorelease];
m_textResponder = [[QIOSTextInputResponder alloc] initWithInputContext:this]; if (inputIsReadOnly) {
qImDebug("creating new read-only text responder");
m_textResponder = [[QIOSTextResponder alloc] initWithInputContext:this];
} else {
qImDebug("creating new read/write text responder");
m_textResponder = [[QIOSTextInputResponder alloc] initWithInputContext:this];
}
} else { } else {
qImDebug("no need to reconfigure keyboard, just notifying input delegate"); qImDebug("no need to reconfigure keyboard, just notifying input delegate");
[m_textResponder notifyInputDelegate:changedProperties]; [m_textResponder notifyInputDelegate:changedProperties];