Fix TextEdit/TextArea mouse cursor shape handling logic

Previously IBeamCursor was wrongly shown in case when TextEdit
was readonly and not selectable by mouse. Now ArrowCursor will be shown
in such case. Additionally removed own mouse cursor shape handling logic
in TextArea, so it will be unified now with derived logic from TextEdit.
This is a change from 23f78b6b76fb9350a472485e34857e1a4842e5d3:
we no longer attempt to restore a cursor that was set via setCursor().

[ChangeLog][QtQuick][TextEdit] TextEdit and TextArea now set their own
mouse cursors more consistently, but without regard for any external
call to setCursor().

Fixes: QTBUG-104089
Pick-to: 6.3 6.4
Change-Id: Iba4e0cb55d555b0f360d7856346ff9e8393b9e1e
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Vladimir Belyavsky 2022-06-08 15:51:45 +03:00 committed by Shawn Rutledge
parent abc8550593
commit 175dfd25c2
5 changed files with 48 additions and 24 deletions

View File

@ -1568,15 +1568,20 @@ bool QQuickTextEdit::selectByMouse() const
void QQuickTextEdit::setSelectByMouse(bool on) void QQuickTextEdit::setSelectByMouse(bool on)
{ {
Q_D(QQuickTextEdit); Q_D(QQuickTextEdit);
if (d->selectByMouse != on) { if (d->selectByMouse == on)
d->selectByMouse = on; return;
setKeepMouseGrab(on);
if (on) d->selectByMouse = on;
d->control->setTextInteractionFlags(d->control->textInteractionFlags() | Qt::TextSelectableByMouse); setKeepMouseGrab(on);
else if (on)
d->control->setTextInteractionFlags(d->control->textInteractionFlags() & ~Qt::TextSelectableByMouse); d->control->setTextInteractionFlags(d->control->textInteractionFlags() | Qt::TextSelectableByMouse);
emit selectByMouseChanged(on); else
} d->control->setTextInteractionFlags(d->control->textInteractionFlags() & ~Qt::TextSelectableByMouse);
#if QT_CONFIG(cursor)
d->updateMouseCursorShape();
#endif
emit selectByMouseChanged(on);
} }
/*! /*!
@ -1638,6 +1643,9 @@ void QQuickTextEdit::setReadOnly(bool r)
#if QT_CONFIG(im) #if QT_CONFIG(im)
updateInputMethod(Qt::ImEnabled); updateInputMethod(Qt::ImEnabled);
#endif
#if QT_CONFIG(cursor)
d->updateMouseCursorShape();
#endif #endif
q_canPasteChanged(); q_canPasteChanged();
emit readOnlyChanged(r); emit readOnlyChanged(r);
@ -2431,7 +2439,7 @@ void QQuickTextEditPrivate::init()
updateDefaultTextOption(); updateDefaultTextOption();
q->updateSize(); q->updateSize();
#if QT_CONFIG(cursor) #if QT_CONFIG(cursor)
q->setCursor(Qt::IBeamCursor); updateMouseCursorShape();
#endif #endif
} }
@ -2715,9 +2723,8 @@ void QQuickTextEdit::q_linkHovered(const QString &link)
emit linkHovered(link); emit linkHovered(link);
#if QT_CONFIG(cursor) #if QT_CONFIG(cursor)
if (link.isEmpty()) { if (link.isEmpty()) {
setCursor(d->cursorToRestoreAfterHover); d->updateMouseCursorShape();
} else if (cursor().shape() != Qt::PointingHandCursor) { } else if (cursor().shape() != Qt::PointingHandCursor) {
d->cursorToRestoreAfterHover = cursor().shape();
setCursor(Qt::PointingHandCursor); setCursor(Qt::PointingHandCursor);
} }
#endif #endif
@ -2728,9 +2735,8 @@ void QQuickTextEdit::q_markerHovered(bool hovered)
Q_D(QQuickTextEdit); Q_D(QQuickTextEdit);
#if QT_CONFIG(cursor) #if QT_CONFIG(cursor)
if (!hovered) { if (!hovered) {
setCursor(d->cursorToRestoreAfterHover); d->updateMouseCursorShape();
} else if (cursor().shape() != Qt::PointingHandCursor) { } else if (cursor().shape() != Qt::PointingHandCursor) {
d->cursorToRestoreAfterHover = cursor().shape();
setCursor(Qt::PointingHandCursor); setCursor(Qt::PointingHandCursor);
} }
#endif #endif
@ -3001,6 +3007,14 @@ bool QQuickTextEditPrivate::isLinkHoveredConnected()
IS_SIGNAL_CONNECTED(q, QQuickTextEdit, linkHovered, (const QString &)); IS_SIGNAL_CONNECTED(q, QQuickTextEdit, linkHovered, (const QString &));
} }
#if QT_CONFIG(cursor)
void QQuickTextEditPrivate::updateMouseCursorShape()
{
Q_Q(QQuickTextEdit);
q->setCursor(q->isReadOnly() && !q->selectByMouse() ? Qt::ArrowCursor : Qt::IBeamCursor);
}
#endif
/*! /*!
\qmlsignal QtQuick::TextEdit::linkHovered(string link) \qmlsignal QtQuick::TextEdit::linkHovered(string link)
\since 5.2 \since 5.2

View File

@ -111,6 +111,10 @@ public:
Qt::LayoutDirection textDirection(const QString &text) const; Qt::LayoutDirection textDirection(const QString &text) const;
bool isLinkHoveredConnected(); bool isLinkHoveredConnected();
#if QT_CONFIG(cursor)
void updateMouseCursorShape();
#endif
void setNativeCursorEnabled(bool) {} void setNativeCursorEnabled(bool) {}
void handleFocusEvent(QFocusEvent *event); void handleFocusEvent(QFocusEvent *event);
void addCurrentTextNodeToRoot(QQuickTextNodeEngine *, QSGTransformNode *, QQuickTextNode*, TextNodeIterator&, int startPos); void addCurrentTextNodeToRoot(QQuickTextNodeEngine *, QSGTransformNode *, QQuickTextNode*, TextNodeIterator&, int startPos);
@ -176,7 +180,6 @@ public:
Qt::InputMethodHints inputMethodHints; Qt::InputMethodHints inputMethodHints;
#endif #endif
UpdateType updateType; UpdateType updateType;
Qt::CursorShape cursorToRestoreAfterHover = Qt::IBeamCursor;
bool dirty : 1; bool dirty : 1;
bool richText : 1; bool richText : 1;

View File

@ -425,9 +425,6 @@ void QQuickTextAreaPrivate::readOnlyChanged(bool isReadOnly)
if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(q_func())) if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(q_func()))
accessibleAttached->set_readOnly(isReadOnly); accessibleAttached->set_readOnly(isReadOnly);
#endif #endif
#if QT_CONFIG(cursor)
q_func()->setCursor(isReadOnly && !selectByMouse ? Qt::ArrowCursor : Qt::IBeamCursor);
#endif
} }
#if QT_CONFIG(accessibility) #if QT_CONFIG(accessibility)
@ -509,9 +506,7 @@ QQuickTextArea::QQuickTextArea(QQuickItem *parent)
setAcceptedMouseButtons(Qt::AllButtons); setAcceptedMouseButtons(Qt::AllButtons);
d->setImplicitResizeEnabled(false); d->setImplicitResizeEnabled(false);
d->pressHandler.control = this; d->pressHandler.control = this;
#if QT_CONFIG(cursor)
setCursor(Qt::IBeamCursor);
#endif
QObjectPrivate::connect(this, &QQuickTextEdit::readOnlyChanged, QObjectPrivate::connect(this, &QQuickTextEdit::readOnlyChanged,
d, &QQuickTextAreaPrivate::readOnlyChanged); d, &QQuickTextAreaPrivate::readOnlyChanged);
} }

View File

@ -2586,8 +2586,6 @@ void tst_qquicktextedit::linkHover()
QCOMPARE(window.cursor().shape(), Qt::IBeamCursor); QCOMPARE(window.cursor().shape(), Qt::IBeamCursor);
QCOMPARE(hover.last()[0].toString(), QString()); QCOMPARE(hover.last()[0].toString(), QString());
texteditObject->setCursor(Qt::OpenHandCursor);
QCursor::setPos(linkPos); QCursor::setPos(linkPos);
QTRY_COMPARE(hover.count(), 3); QTRY_COMPARE(hover.count(), 3);
QCOMPARE(window.cursor().shape(), Qt::PointingHandCursor); QCOMPARE(window.cursor().shape(), Qt::PointingHandCursor);
@ -2595,7 +2593,7 @@ void tst_qquicktextedit::linkHover()
QCursor::setPos(textPos); QCursor::setPos(textPos);
QTRY_COMPARE(hover.count(), 4); QTRY_COMPARE(hover.count(), 4);
QCOMPARE(window.cursor().shape(), Qt::OpenHandCursor); QCOMPARE(window.cursor().shape(), Qt::IBeamCursor);
QCOMPARE(hover.last()[0].toString(), QString()); QCOMPARE(hover.last()[0].toString(), QString());
} }
#endif #endif

View File

@ -33,6 +33,7 @@ private slots:
void editable(); void editable();
void pageIndicator(); void pageIndicator();
void scrollBar(); void scrollBar();
void textArea();
}; };
tst_cursor::tst_cursor() tst_cursor::tst_cursor()
@ -200,6 +201,19 @@ void tst_cursor::scrollBar()
QCOMPARE(window->cursor().shape(), textArea->cursor().shape()); QCOMPARE(window->cursor().shape(), textArea->cursor().shape());
} }
// QTBUG-104089
void tst_cursor::textArea()
{
QQuickTextArea textArea;
QCOMPARE(textArea.cursor().shape(), Qt::IBeamCursor);
textArea.setReadOnly(true);
QCOMPARE(textArea.cursor().shape(), Qt::ArrowCursor);
textArea.setSelectByMouse(true);
QCOMPARE(textArea.cursor().shape(), Qt::IBeamCursor);
}
QTEST_MAIN(tst_cursor) QTEST_MAIN(tst_cursor)
#include "tst_cursor.moc" #include "tst_cursor.moc"