summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/ios/qiosinputcontext.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/ios/qiosinputcontext.mm')
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm35
1 files changed, 29 insertions, 6 deletions
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index d2229df133..ac75367d7f 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -160,7 +160,7 @@ static QUIView *focusView()
return;
// Enable hide-keyboard gesture
- self.enabled = YES;
+ self.enabled = m_context->isInputPanelVisible();
m_context->scrollToCursor();
}
@@ -402,7 +402,7 @@ void QIOSInputContext::updateKeyboardState(NSNotification *notification)
// The isInputPanelVisible() property is based on whether or not the virtual keyboard
// is visible on screen, and does not follow the logic of the iOS WillShow and WillHide
// notifications which are not emitted for undocked keyboards, and are buggy when dealing
- // with input-accesosory-views. The reason for using frameEnd here (the future state),
+ // with input-accessory-views. The reason for using frameEnd here (the future state),
// instead of the current state reflected in frameBegin, is that QInputMethod::isVisible()
// is documented to reflect the future state in the case of animated transitions.
m_keyboardState.keyboardVisible = CGRectIntersectsRect(frameEnd, [UIScreen mainScreen].bounds);
@@ -667,7 +667,8 @@ void QIOSInputContext::update(Qt::InputMethodQueries updatedProperties)
// focus object. We try to detect code paths that fail this assertion and smooth
// over the situation by doing a manual update of the focus object.
if (qApp->focusObject() != m_imeState.focusObject && updatedProperties != Qt::ImQueryAll) {
- qWarning() << "stale focus object" << m_imeState.focusObject << ", doing manual update";
+ qWarning() << "stale focus object" << static_cast<void *>(m_imeState.focusObject)
+ << ", doing manual update";
setFocusObject(qApp->focusObject());
return;
}
@@ -726,12 +727,34 @@ 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).
+ const auto oldResponder = m_textResponder;
+ [m_textResponder setMarkedText:@"" selectedRange:NSMakeRange(0, 0)];
+ [m_textResponder notifyInputDelegate:Qt::ImQueryInput];
+ [m_textResponder autorelease];
+ m_textResponder = nullptr;
update(Qt::ImQueryAll);
- [m_textResponder setMarkedText:@"" selectedRange:NSMakeRange(0, 0)];
- [m_textResponder notifyInputDelegate:Qt::ImQueryInput];
+ // If update() didn't end up creating a new text responder, oldResponder will still be
+ // the first responder. In that case we need to resign it, so that the input panel hides.
+ // (the input panel will apparently not hide if the first responder is only released).
+ if ([oldResponder isFirstResponder]) {
+ qImDebug("IM not enabled, resigning autoreleased text responder as first responder");
+ [oldResponder resignFirstResponder];
+ }
}
/*!