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.mm49
1 files changed, 39 insertions, 10 deletions
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index 68088540c6..237077400b 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -498,15 +498,32 @@ void QIOSInputContext::scrollToCursor()
return;
}
- const int margin = 20;
- QRectF translatedCursorPos = qApp->inputMethod()->cursorRectangle();
- translatedCursorPos.translate(focusView().qwindow->geometry().topLeft());
-
- qreal keyboardY = [rootView convertRect:m_keyboardState.keyboardEndRect fromView:nil].origin.y;
- int statusBarY = qGuiApp->primaryScreen()->availableGeometry().y();
+ QWindow *focusWindow = qApp->focusWindow();
+ QRect cursorRect = qApp->inputMethod()->cursorRectangle().translated(focusWindow->geometry().topLeft()).toRect();
+ if (cursorRect.isNull()) {
+ scroll(0);
+ return;
+ }
- scroll((translatedCursorPos.bottomLeft().y() < keyboardY - margin) ? 0
- : qMin(rootView.bounds.size.height - keyboardY, translatedCursorPos.y() - statusBarY - margin));
+ // Add some padding so that the cusor does not end up directly above the keyboard
+ static const int kCursorRectPadding = 20;
+ cursorRect.adjust(0, -kCursorRectPadding, 0, kCursorRectPadding);
+
+ // We explicitly ask for the geometry of the screen instead of the availableGeometry,
+ // as we hide the statusbar when scrolling the screen, so the available geometry will
+ // include the space taken by the status bar at the moment.
+ QRect screenGeometry = focusWindow->screen()->geometry();
+ QRect keyboardGeometry = QRectF::fromCGRect(m_keyboardState.keyboardEndRect).toRect();
+ QRect availableGeometry = (QRegion(screenGeometry) - keyboardGeometry).boundingRect();
+
+ if (!availableGeometry.contains(cursorRect, true)) {
+ qImDebug() << "cursor rect" << cursorRect << "not fully within" << availableGeometry;
+ int scrollToCenter = -(availableGeometry.center() - cursorRect.center()).y();
+ int scrollToBottom = focusWindow->screen()->geometry().bottom() - availableGeometry.bottom();
+ scroll(qMin(scrollToCenter, scrollToBottom));
+ } else {
+ scroll(0);
+ }
}
void QIOSInputContext::scroll(int y)
@@ -519,6 +536,8 @@ void QIOSInputContext::scroll(int y)
if (CATransform3DEqualToTransform(translationTransform, rootView.layer.sublayerTransform))
return;
+ qImDebug() << "scrolling root view to y =" << -y;
+
QPointer<QIOSInputContext> self = this;
[UIView animateWithDuration:m_keyboardState.animationDuration delay:0
options:(m_keyboardState.animationCurve << 16) | UIViewAnimationOptionBeginFromCurrentState
@@ -631,11 +650,21 @@ void QIOSInputContext::focusWindowChanged(QWindow *focusWindow)
*/
void QIOSInputContext::update(Qt::InputMethodQueries updatedProperties)
{
+ qImDebug() << "fw =" << qApp->focusWindow() << "fo =" << qApp->focusObject();
+
+ // Changes to the focus object should always result in a call to setFocusObject(),
+ // triggering a reset() which will update all the properties based on the new
+ // 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";
+ setFocusObject(qApp->focusObject());
+ return;
+ }
+
// 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);
- qImDebug() << "fw =" << qApp->focusWindow() << "fo =" << qApp->focusObject();
-
// Perform update first, so we can trust the value of inputMethodAccepted()
Qt::InputMethodQueries changedProperties = m_imeState.update(updatedProperties);