Android: Fix select handles misplacement on QDialog
Get select handles {Left, Right}Point from a mapToGlobal with a cursorRectangleof anchorRectangle
of the selected word/text.
Task-number: QTBUG-90799
Change-Id: I4fed19a1d3bb2247656b052306307e6980074405
Reviewed-by: Rami Potinkara <rami.potinkara@qt.io>
Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
bb10
parent
13c8db52a2
commit
32cdf0ce0f
|
|
@ -202,6 +202,11 @@ public class CursorHandle implements ViewTreeObserver.OnPreDrawListener
|
|||
}
|
||||
}
|
||||
|
||||
public int width()
|
||||
{
|
||||
return m_cursorView.getDrawable().getIntrinsicWidth();
|
||||
}
|
||||
|
||||
// The handle was dragged by a given relative position
|
||||
public void updatePosition(int x, int y) {
|
||||
y -= m_yShift;
|
||||
|
|
|
|||
|
|
@ -513,6 +513,17 @@ public class QtActivityDelegate
|
|||
private static final int CursorHandleShowSelection = 2;
|
||||
private static final int CursorHandleShowEdit = 0x100;
|
||||
|
||||
public int getSelectHandleWidth()
|
||||
{
|
||||
int width = 0;
|
||||
if (m_leftSelectionHandle != null && m_rightSelectionHandle != null) {
|
||||
width = Math.max(m_leftSelectionHandle.width(), m_rightSelectionHandle.width());
|
||||
} else if (m_cursorHandle != null) {
|
||||
width = m_cursorHandle.width();
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
/* called from the C++ code when the position of the cursor or selection handles needs to
|
||||
be adjusted.
|
||||
mode is one of QAndroidInputContext::CursorHandleShowMode
|
||||
|
|
|
|||
|
|
@ -864,6 +864,11 @@ public class QtNative
|
|||
});
|
||||
}
|
||||
|
||||
private static int getSelectHandleWidth()
|
||||
{
|
||||
return m_activityDelegate.getSelectHandleWidth();
|
||||
}
|
||||
|
||||
private static void updateHandles(final int mode,
|
||||
final int editX,
|
||||
final int editY,
|
||||
|
|
|
|||
|
|
@ -121,6 +121,11 @@ namespace QtAndroidInput
|
|||
return m_softwareKeyboardRect;
|
||||
}
|
||||
|
||||
int getSelectHandleWidth()
|
||||
{
|
||||
return QJniObject::callStaticMethod<jint>(applicationClass(), "getSelectHandleWidth");
|
||||
}
|
||||
|
||||
void updateHandles(int mode, QPoint editMenuPos, uint32_t editButtons, QPoint cursor, QPoint anchor, bool rtl)
|
||||
{
|
||||
QJniObject::callStaticMethod<void>(applicationClass(), "updateHandles", "(IIIIIIIIZ)V",
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ namespace QtAndroidInput
|
|||
// cursor/selection handles
|
||||
void updateHandles(int handleCount, QPoint editMenuPos = QPoint(), uint32_t editButtons = 0,
|
||||
QPoint cursor = QPoint(), QPoint anchor = QPoint(), bool rtl = false);
|
||||
int getSelectHandleWidth();
|
||||
|
||||
bool registerNatives(JNIEnv *env);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ private:
|
|||
static QAndroidInputContext *m_androidInputContext = nullptr;
|
||||
static char const *const QtNativeInputConnectionClassName = "org/qtproject/qt/android/QtNativeInputConnection";
|
||||
static char const *const QtExtractedTextClassName = "org/qtproject/qt/android/QtExtractedText";
|
||||
static int m_selectHandleWidth = 0;
|
||||
static jclass m_extractedTextClass = 0;
|
||||
static jmethodID m_classConstructorMethodID = 0;
|
||||
static jfieldID m_partialEndOffsetFieldID = 0;
|
||||
|
|
@ -609,7 +610,6 @@ void QAndroidInputContext::updateSelectionHandles()
|
|||
|
||||
auto im = qGuiApp->inputMethod();
|
||||
|
||||
|
||||
QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImAnchorPosition | Qt::ImEnabled
|
||||
| Qt::ImCurrentSelection | Qt::ImHints | Qt::ImSurroundingText
|
||||
| Qt::ImReadOnly);
|
||||
|
|
@ -619,6 +619,7 @@ void QAndroidInputContext::updateSelectionHandles()
|
|||
int anchor = query.value(Qt::ImAnchorPosition).toInt();
|
||||
const QVariant readOnlyVariant = query.value(Qt::ImReadOnly);
|
||||
bool readOnly = readOnlyVariant.toBool();
|
||||
QPlatformWindow *qPlatformWindow = qGuiApp->focusWindow()->handle();
|
||||
|
||||
if ( cpos == anchor && (!readOnlyVariant.isValid() || readOnly)) {
|
||||
QtAndroidInput::updateHandles(Hidden);
|
||||
|
|
@ -627,7 +628,7 @@ void QAndroidInputContext::updateSelectionHandles()
|
|||
|
||||
if (cpos == anchor || im->anchorRectangle().isNull()) {
|
||||
auto curRect = cursorRectangle();
|
||||
QPoint cursorPoint = qGuiApp->focusWindow()->handle()->mapToGlobal(QPoint(curRect.x() + (curRect.width() / 2), curRect.y() + curRect.height()));
|
||||
QPoint cursorPoint = qPlatformWindow->mapToGlobal(QPoint(curRect.x() + (curRect.width() / 2), curRect.y() + curRect.height()));
|
||||
QPoint editMenuPoint(cursorPoint.x(), cursorPoint.y());
|
||||
m_handleMode &= ShowEditPopup;
|
||||
m_handleMode |= ShowCursor;
|
||||
|
|
@ -646,14 +647,26 @@ void QAndroidInputContext::updateSelectionHandles()
|
|||
auto rightRect = anchorRectangle();
|
||||
if (cpos > anchor)
|
||||
std::swap(leftRect, rightRect);
|
||||
//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(qPlatformWindow->mapToGlobal(leftRect.bottomLeft().toPoint()));
|
||||
QPoint rightPoint(qPlatformWindow->mapToGlobal(rightRect.bottomRight().toPoint()));
|
||||
|
||||
QPoint leftPoint(leftRect.bottomLeft().toPoint());
|
||||
QPoint righPoint(rightRect.bottomRight().toPoint());
|
||||
QPoint editPoint(leftRect.united(rightRect).topLeft().toPoint());
|
||||
if (m_selectHandleWidth == 0)
|
||||
m_selectHandleWidth = QtAndroidInput::getSelectHandleWidth() / 2;
|
||||
int rightSideOfScreen = QtAndroid::androidPlatformIntegration()->screen()->availableGeometry().right();
|
||||
if (leftPoint.x() < m_selectHandleWidth)
|
||||
leftPoint.setX(m_selectHandleWidth);
|
||||
|
||||
if (rightPoint.x() > rightSideOfScreen - m_selectHandleWidth)
|
||||
rightPoint.setX(rightSideOfScreen - m_selectHandleWidth);
|
||||
|
||||
QPoint editPoint(qPlatformWindow->mapToGlobal(leftRect.united(rightRect).topLeft().toPoint()));
|
||||
uint32_t buttons = readOnly ? EditContext::CopyButton | EditContext::SelectAllButton
|
||||
: EditContext::AllButtons;
|
||||
|
||||
QtAndroidInput::updateHandles(m_handleMode, editPoint, buttons, leftPoint, righPoint,
|
||||
QtAndroidInput::updateHandles(m_handleMode, editPoint, buttons, leftPoint, rightPoint,
|
||||
query.value(Qt::ImCurrentSelection).toString().isRightToLeft());
|
||||
m_hideCursorHandleTimer.stop();
|
||||
}
|
||||
|
|
@ -690,7 +703,23 @@ void QAndroidInputContext::handleLocationChanged(int handleId, int x, int y)
|
|||
}
|
||||
|
||||
bool ok;
|
||||
const int handlePos = queryFocusObject(Qt::ImCursorPosition, point).toInt(&ok);
|
||||
auto object = m_focusObject->parent();
|
||||
int dialogMoveX = 0;
|
||||
while (object) {
|
||||
if (QString::compare(object->metaObject()->className(),
|
||||
"QDialog", Qt::CaseInsensitive) == 0) {
|
||||
dialogMoveX += object->property("x").toInt();
|
||||
}
|
||||
object = object->parent();
|
||||
};
|
||||
|
||||
auto position =
|
||||
QPointF(QHighDpi::fromNativePixels(point, QGuiApplication::focusWindow()));
|
||||
const QPointF fixedPosition = QPointF(position.x() - dialogMoveX, position.y());
|
||||
const QInputMethod *im = QGuiApplication::inputMethod();
|
||||
const QTransform mapToLocal = im->inputItemTransform().inverted();
|
||||
const int handlePos = im->queryFocusObject(Qt::ImCursorPosition, mapToLocal.map(fixedPosition)).toInt(&ok);
|
||||
|
||||
if (!ok)
|
||||
return;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue