QWidget: use WA_InputMethodEnabled when ImEnabled is not implemented

In Qt 6.3, a check for WA_InputMethodEnabled was removed
in QWidget, to support IM queries also for read-only
widgets (7c6e4af48). This caused a regression on iOS, which
made the input panel open for widgets that didn't support
IM at all.

A patch was merged that solved the regression (3b12305575),
but it didn't take the widget attribute into account.
Since not doing so has the potential to cause regressions,
this patch will modify the affected code once more, so that
we instead fall back to test WA_InputMethodEnabled when
ImEnabled is not implemented. This will match closely
to the way ImEnabled was implemented in Qt 6.2.

Since we, with this change, now require that either ImEnabled
or WA_InputMethodEnabled is set, our own input widgets will
fail to support IM text selection when they're read-only, since
they actually don't implement ImEnabled.
This patch will therefore also make sure that we do so.

Task-number: QTBUG-104527
Change-Id: I70ad910aec38d0a74f4dd7d3115d3c45c16d2b3b
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit e44edaac2c575df9b2f065b18b716cb21a0c2b75)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Richard Moe Gustavsen 2022-07-06 15:59:37 +02:00 committed by Qt Cherry-pick Bot
parent c9c3f57883
commit c0db9e9082
6 changed files with 21 additions and 10 deletions

View File

@ -10274,7 +10274,9 @@ void QGraphicsTextItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
QVariant QGraphicsTextItem::inputMethodQuery(Qt::InputMethodQuery query) const QVariant QGraphicsTextItem::inputMethodQuery(Qt::InputMethodQuery query) const
{ {
QVariant v; QVariant v;
if (query == Qt::ImHints) if (query == Qt::ImEnabled)
return isEnabled();
else if (query == Qt::ImHints)
v = int(inputMethodHints()); v = int(inputMethodHints());
else if (dd->control) else if (dd->control)
v = dd->control->inputMethodQuery(query, QVariant()); v = dd->control->inputMethodQuery(query, QVariant());

View File

@ -8898,15 +8898,12 @@ bool QWidget::event(QEvent *event)
QVariant v = inputMethodQuery(q); QVariant v = inputMethodQuery(q);
if (q == Qt::ImEnabled && !v.isValid() && isEnabled()) { if (q == Qt::ImEnabled && !v.isValid() && isEnabled()) {
// Qt:ImEnabled was added in Qt 5.3. So not all widgets support it, even // Qt:ImEnabled was added in Qt 5.3. So not all widgets support it, even
// if they implement IM otherwise (and override inputMethodQuery()). // if they implement IM otherwise (by overriding inputMethodQuery()). Instead
// So for legacy reasons, we need to check by other means if IM is supported when // they set the widget attribute Qt::WA_InputMethodEnabled. But this attribute
// Qt::ImEnabled is not implemented (the query returns an invalid QVariant). // will only be set if the widget supports IM _and_ is not read-only. So for
// Since QWidget implements inputMethodQuery(), and return valid values for // read-only widgets, not all IM features will be supported when ImEnabled is
// some of the IM properties, we cannot just query for Qt::ImQueryAll. // not implemented explicitly (e.g selection handles for read-only widgets on iOS).
// Instead we assume that if a widget supports IM, it will implement v = QVariant(testAttribute(Qt::WA_InputMethodEnabled));
// Qt::ImSurroundingText (which is not implemented by QWidget).
const bool imEnabledFallback = inputMethodQuery(Qt::ImSurroundingText).isValid();
v = QVariant(imEnabledFallback);
} }
query->setValue(q, v); query->setValue(q, v);
} }

View File

@ -1811,6 +1811,8 @@ QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property, QVariant arg
{ {
Q_D(const QLineEdit); Q_D(const QLineEdit);
switch(property) { switch(property) {
case Qt::ImEnabled:
return isEnabled();
case Qt::ImCursorRectangle: case Qt::ImCursorRectangle:
return d->cursorRect(); return d->cursorRect();
case Qt::ImAnchorRectangle: case Qt::ImAnchorRectangle:

View File

@ -2206,6 +2206,8 @@ QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant a
{ {
Q_D(const QPlainTextEdit); Q_D(const QPlainTextEdit);
switch (query) { switch (query) {
case Qt::ImEnabled:
return isEnabled();
case Qt::ImHints: case Qt::ImHints:
case Qt::ImInputItemClipRectangle: case Qt::ImInputItemClipRectangle:
return QWidget::inputMethodQuery(query); return QWidget::inputMethodQuery(query);

View File

@ -1803,6 +1803,8 @@ QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery query, QVariant argume
{ {
Q_D(const QTextEdit); Q_D(const QTextEdit);
switch (query) { switch (query) {
case Qt::ImEnabled:
return isEnabled();
case Qt::ImHints: case Qt::ImHints:
case Qt::ImInputItemClipRectangle: case Qt::ImInputItemClipRectangle:
return QWidget::inputMethodQuery(query); return QWidget::inputMethodQuery(query);

View File

@ -11011,6 +11011,12 @@ void tst_QWidget::imEnabledNotImplemented()
imEnabled = QApplication::inputMethod()->queryFocusObject(Qt::ImEnabled, QVariant()); imEnabled = QApplication::inputMethod()->queryFocusObject(Qt::ImEnabled, QVariant());
QVERIFY(imEnabled.isValid()); QVERIFY(imEnabled.isValid());
QVERIFY(imEnabled.toBool()); QVERIFY(imEnabled.toBool());
// ...even if it's read-only
edit.setReadOnly(true);
imEnabled = QApplication::inputMethod()->queryFocusObject(Qt::ImEnabled, QVariant());
QVERIFY(imEnabled.isValid());
QVERIFY(imEnabled.toBool());
} }
#ifdef QT_BUILD_INTERNAL #ifdef QT_BUILD_INTERNAL