iOS: update keyboard layout upon focus transfer

When iOS transfers focus from one view to another, it
asks the new view for its UIKeyInput properties before
deciding how the keyboard should be configured.

For Qt, the same QUIView is used for the whole QWindow
which means that UIKit will not change the keyboard
configuration just because we change the focus object
in Qt, since the UIView does not change.

There seems to be no way to tell UIKit that the
keyboard needs to change becuse the UIKeyInput
properties has changed. To work around this, we
briefly resign first responder status, and grabs it
again, for the same QUIView.

Change-Id: I2d15cc0c928deb023e7da58ad4669b7099dce2cf
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@digia.com>
This commit is contained in:
Richard Moe Gustavsen 2013-11-16 10:59:17 +01:00 committed by The Qt Project
parent bdf0670c02
commit 484d6ce776
2 changed files with 19 additions and 2 deletions

View File

@ -71,6 +71,7 @@ private:
UIView<UIKeyInput> *m_focusView;
QTransform m_inputItemTransform;
bool m_hasPendingHideRequest;
bool m_inSetFocusObject;
};
QT_END_NAMESPACE

View File

@ -170,6 +170,7 @@ QIOSInputContext::QIOSInputContext()
, m_keyboardListener([[QIOSKeyboardListener alloc] initWithQIOSInputContext:this])
, m_focusView(0)
, m_hasPendingHideRequest(false)
, m_inSetFocusObject(false)
{
if (isQtApplication())
connect(qGuiApp->inputMethod(), &QInputMethod::cursorRectangleChanged, this, &QIOSInputContext::scrollRootView);
@ -218,7 +219,22 @@ bool QIOSInputContext::isInputPanelVisible() const
void QIOSInputContext::setFocusObject(QObject *)
{
m_inputItemTransform = qApp->inputMethod()->inputItemTransform();
scrollRootView();
if (!m_focusView || !m_focusView.isFirstResponder)
return;
// Since m_focusView is the first responder, it means that the keyboard is open and we
// should update keyboard layout. But there seem to be no way to tell it to reread the
// UITextInputTraits from m_focusView. To work around that, we quickly resign first
// responder status just to reassign it again. To not remove the focusObject in the same
// go, we need to call the super implementation of resignFirstResponder. Since the call
// will cause a 'keyboardWillHide' notification to be sendt, we also block scrollRootView
// to avoid artifacts:
m_inSetFocusObject = true;
SEL sel = @selector(resignFirstResponder);
[[m_focusView superclass] instanceMethodForSelector:sel](m_focusView, sel);
m_inSetFocusObject = false;
[m_focusView becomeFirstResponder];
}
void QIOSInputContext::focusWindowChanged(QWindow *focusWindow)
@ -238,7 +254,7 @@ void QIOSInputContext::scrollRootView()
// - the first responder is a QUIView, and not some other foreign UIView.
// - the keyboard is docked. Otherwise the user can move the keyboard instead.
// - the inputItem has not been moved/scrolled
if (!isQtApplication() || !m_focusView)
if (!isQtApplication() || !m_focusView || m_inSetFocusObject)
return;
if (m_inputItemTransform != qApp->inputMethod()->inputItemTransform()) {