summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/android/qandroidinputcontext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/android/qandroidinputcontext.cpp')
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp90
1 files changed, 73 insertions, 17 deletions
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index 2cfb59514d..8a44482d44 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -47,6 +47,7 @@
#include "qandroideventdispatcher.h"
#include "androiddeadlockprotector.h"
#include "qandroidplatformintegration.h"
+#include <private/qhighdpiscaling_p.h>
#include <QDebug>
#include <qevent.h>
#include <qguiapplication.h>
@@ -94,6 +95,7 @@ private:
static QAndroidInputContext *m_androidInputContext = 0;
static char const *const QtNativeInputConnectionClassName = "org/qtproject/qt5/android/QtNativeInputConnection";
static char const *const QtExtractedTextClassName = "org/qtproject/qt5/android/QtExtractedText";
+static char const *const QtObjectType = "QDialog";
static jclass m_extractedTextClass = 0;
static jmethodID m_classConstructorMethodID = 0;
static jfieldID m_partialEndOffsetFieldID = 0;
@@ -512,7 +514,12 @@ QAndroidInputContext::QAndroidInputContext()
auto im = qGuiApp->inputMethod();
if (!im->inputItemClipRectangle().contains(im->anchorRectangle()) ||
!im->inputItemClipRectangle().contains(im->cursorRectangle())) {
- m_handleMode = Hidden;
+ // Undoes the hidden request if the only reason for the hidden is that
+ // X of the cursorRectangle or X of the anchorRectangle is less than 0.
+ const int rectX = im->inputItemClipRectangle().x();
+ if (im->cursorRectangle().x() > rectX && im->anchorRectangle().x() > rectX)
+ m_handleMode = Hidden;
+
updateSelectionHandles();
}
});
@@ -621,13 +628,13 @@ void QAndroidInputContext::updateSelectionHandles()
if (noHandles)
return;
+ QWindow *window = qGuiApp->focusWindow();
auto im = qGuiApp->inputMethod();
- if (!m_focusObject || ((m_handleMode & 0xff) == Hidden)) {
+ if (!m_focusObject || ((m_handleMode & 0xff) == Hidden) || !window) {
// Hide the handles
QtAndroidInput::updateHandles(Hidden);
return;
}
- QWindow *window = qGuiApp->focusWindow();
double pixelDensity = window
? QHighDpiScaling::factor(window)
: QHighDpiScaling::factor(QtAndroid::androidPlatformIntegration()->screen());
@@ -645,14 +652,25 @@ void QAndroidInputContext::updateSelectionHandles()
}
auto curRect = im->cursorRectangle();
+ QPoint cursorPointGlobal = window->mapToGlobal(QPoint(curRect.x() + (curRect.width() / 2), curRect.y() + curRect.height()));
QPoint cursorPoint(curRect.center().x(), curRect.bottom());
- QPoint editMenuPoint(curRect.x(), curRect.y());
+ int x = curRect.x();
+ int y = curRect.y();
+
+ // Use x and y for the editMenuPoint from the cursorPointGlobal when the cursor is in the Dialog
+ if (cursorPointGlobal != cursorPoint) {
+ x = cursorPointGlobal.x();
+ y = cursorPointGlobal.y();
+ }
+
+ QPoint editMenuPoint(x, y);
m_handleMode &= ShowEditPopup;
m_handleMode |= ShowCursor;
uint32_t buttons = EditContext::PasteButton;
if (!query.value(Qt::ImSurroundingText).toString().isEmpty())
buttons |= EditContext::SelectAllButton;
- QtAndroidInput::updateHandles(m_handleMode, editMenuPoint * pixelDensity, buttons, cursorPoint * pixelDensity);
+ QtAndroidInput::updateHandles(m_handleMode, editMenuPoint * pixelDensity, buttons,
+ cursorPointGlobal * pixelDensity);
// The VK is hidden, reset the timer
if (m_hideCursorHandleTimer.isActive())
m_hideCursorHandleTimer.start();
@@ -665,10 +683,30 @@ void QAndroidInputContext::updateSelectionHandles()
if (cpos > anchor)
std::swap(leftRect, rightRect);
- QPoint leftPoint(leftRect.bottomLeft().toPoint() * pixelDensity);
- QPoint righPoint(rightRect.bottomRight().toPoint() * pixelDensity);
- QPoint editPoint(leftRect.united(rightRect).topLeft().toPoint() * pixelDensity);
- QtAndroidInput::updateHandles(m_handleMode, editPoint, EditContext::AllButtons, leftPoint, righPoint,
+ // Move the left or right select handle to the center from the screen edge
+ // the select handle is close to or over the screen edge. Otherwise, the
+ // select handle might go out of the screen and it would be impossible to drag.
+ QPoint leftPoint(window->mapToGlobal(leftRect.bottomLeft().toPoint()));
+ QPoint rightPoint(window->mapToGlobal(rightRect.bottomRight().toPoint()));
+ static int m_selectHandleWidth = 0;
+ // For comparison, get the width of the handle.
+ // Only half of the width will protrude from the cursor on each side
+ if (m_selectHandleWidth == 0)
+ m_selectHandleWidth = QtAndroidInput::getSelectHandleWidth() / 2;
+
+ int rightSideOfScreen = QtAndroid::androidPlatformIntegration()->screen()->availableGeometry().right();
+
+ // Check if handle will fit the screen on left side. If not, then move it closer to the center
+ if (leftPoint.x() <= m_selectHandleWidth)
+ leftPoint.setX(m_selectHandleWidth / pixelDensity);
+
+ // Check if handle will fit the screen on right side. If not, then move it closer to the center
+ if (rightPoint.x() >= (rightSideOfScreen / pixelDensity) - m_selectHandleWidth)
+ rightPoint.setX((rightSideOfScreen / pixelDensity) - (m_selectHandleWidth / pixelDensity));
+
+ QPoint editPoint(window->mapToGlobal(leftRect.united(rightRect).topLeft().toPoint()));
+ QtAndroidInput::updateHandles(m_handleMode, editPoint * pixelDensity, EditContext::AllButtons,
+ leftPoint * pixelDensity, rightPoint * pixelDensity,
query.value(Qt::ImCurrentSelection).toString().isRightToLeft());
m_hideCursorHandleTimer.stop();
}
@@ -692,7 +730,17 @@ void QAndroidInputContext::handleLocationChanged(int handleId, int x, int y)
double pixelDensity = window
? QHighDpiScaling::factor(window)
: QHighDpiScaling::factor(QtAndroid::androidPlatformIntegration()->screen());
- QPointF point(x / pixelDensity, y / pixelDensity);
+ auto object = m_focusObject->parent();
+ int dialogMoveX = 0;
+ while (object) {
+ if (QString::compare(object->metaObject()->className(),
+ QtObjectType, Qt::CaseInsensitive) == 0) {
+ dialogMoveX += object->property("x").toInt();
+ }
+ object = object->parent();
+ };
+
+ QPointF point((x / pixelDensity) - dialogMoveX, y / pixelDensity);
point.setY(point.y() - leftRect.width() / 2);
QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImAnchorPosition
@@ -1195,13 +1243,21 @@ bool QAndroidInputContext::focusObjectStopComposing()
m_composingCursor = -1;
- // Moving Qt's cursor to where the preedit cursor used to be
- QList<QInputMethodEvent::Attribute> attributes;
- attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, localCursorPos, 0));
-
- QInputMethodEvent event(QString(), attributes);
- event.setCommitString(m_composingText);
- sendInputMethodEvent(&event);
+ {
+ // commit the composing test
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event(QString(), attributes);
+ event.setCommitString(m_composingText);
+ sendInputMethodEvent(&event);
+ }
+ {
+ // Moving Qt's cursor to where the preedit cursor used to be
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes.append(
+ QInputMethodEvent::Attribute(QInputMethodEvent::Selection, localCursorPos, 0));
+ QInputMethodEvent event(QString(), attributes);
+ sendInputMethodEvent(&event);
+ }
return true;
}