summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2009-11-13 15:56:21 (GMT)
committerSimon Hausmann <simon.hausmann@nokia.com>2009-11-13 15:58:43 (GMT)
commit851814cfedd678bfdf019eeafecd085b9df9058f (patch)
tree96dd9fbde0f0280677684b2dbb1e7f012129c76f
parentead0ab9e14603f278fcaaf4f126cdd232274fe26 (diff)
downloadQt-851814cfedd678bfdf019eeafecd085b9df9058f.zip
Qt-851814cfedd678bfdf019eeafecd085b9df9058f.tar.gz
Qt-851814cfedd678bfdf019eeafecd085b9df9058f.tar.bz2
Fix input method support on widgets that have a focus proxy set.
When enabling/disabling a widget or changing its InputMethodEnabled attribute, use the focus proxy widget's input context for reset and for setting the focus widget on the input context. Task-number: QTBUG-5781 Reviewed-by: Denis
-rw-r--r--src/gui/kernel/qwidget.cpp21
-rw-r--r--src/gui/kernel/qwidget_p.h6
-rw-r--r--tests/auto/qwidget/tst_qwidget.cpp59
3 files changed, 77 insertions, 9 deletions
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 4aa358f..0d8da0c 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -3084,9 +3084,10 @@ void QWidgetPrivate::setEnabled_helper(bool enable)
#endif
#ifndef QT_NO_IM
if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
- QInputContext *qic = inputContext();
+ QWidget *focusWidget = effectiveFocusWidget();
+ QInputContext *qic = focusWidget->d_func()->inputContext();
if (enable) {
- qic->setFocusWidget(q);
+ qic->setFocusWidget(focusWidget);
} else {
qic->reset();
qic->setFocusWidget(0);
@@ -10348,9 +10349,10 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
break; }
case Qt::WA_NativeWindow: {
#ifndef QT_NO_IM
+ QWidget *focusWidget = d->effectiveFocusWidget();
QInputContext *ic = 0;
if (on && !internalWinId() && testAttribute(Qt::WA_InputMethodEnabled) && hasFocus()) {
- ic = d->inputContext();
+ ic = focusWidget->d_func()->inputContext();
ic->reset();
ic->setFocusWidget(0);
}
@@ -10359,7 +10361,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
d->createWinId();
if (ic && isEnabled())
- ic->setFocusWidget(this);
+ ic->setFocusWidget(focusWidget);
#endif //QT_NO_IM
break;
}
@@ -10391,13 +10393,14 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
break;
case Qt::WA_InputMethodEnabled: {
#ifndef QT_NO_IM
- QInputContext *ic = d->ic;
+ QWidget *focusWidget = d->effectiveFocusWidget();
+ QInputContext *ic = focusWidget->d_func()->ic;
if (!ic && (!on || hasFocus()))
- ic = d->inputContext();
+ ic = focusWidget->d_func()->inputContext();
if (ic) {
- if (on && hasFocus() && ic->focusWidget() != this && isEnabled()) {
- ic->setFocusWidget(this);
- } else if (!on && ic->focusWidget() == this) {
+ if (on && hasFocus() && ic->focusWidget() != focusWidget && isEnabled()) {
+ ic->setFocusWidget(focusWidget);
+ } else if (!on && ic->focusWidget() == focusWidget) {
ic->reset();
ic->setFocusWidget(0);
}
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index eea929b..66efcb5 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -465,6 +465,12 @@ public:
void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = 0);
QInputContext *inputContext() const;
+ inline QWidget *effectiveFocusWidget() {
+ QWidget *w = q_func();
+ while (w->focusProxy())
+ w = w->focusProxy();
+ return w;
+ }
void setModal_sys();
diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp
index e027dd1..9692c6e 100644
--- a/tests/auto/qwidget/tst_qwidget.cpp
+++ b/tests/auto/qwidget/tst_qwidget.cpp
@@ -388,6 +388,8 @@ private slots:
void cbaVisibility();
#endif
+ void focusProxyAndInputMethods();
+
private:
bool ensureScreenSize(int width, int height);
QWidget *testWidget;
@@ -9619,5 +9621,62 @@ void tst_QWidget::cbaVisibility()
}
#endif
+class InputContextTester : public QInputContext
+{
+ Q_OBJECT
+public:
+ QString identifierName() { return QString(); }
+ bool isComposing() const { return false; }
+ QString language() { return QString(); }
+ void reset() { ++resets; }
+ int resets;
+};
+
+void tst_QWidget::focusProxyAndInputMethods()
+{
+ InputContextTester *inputContext = new InputContextTester;
+ QWidget *toplevel = new QWidget(0, Qt::X11BypassWindowManagerHint);
+ toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
+ toplevel->setInputContext(inputContext); // ownership is transferred
+
+ QWidget *child = new QWidget(toplevel);
+ child->setFocusProxy(toplevel);
+ child->setAttribute(Qt::WA_InputMethodEnabled, true);
+
+ toplevel->setFocusPolicy(Qt::WheelFocus);
+ child->setFocusPolicy(Qt::WheelFocus);
+
+ QVERIFY(!child->hasFocus());
+ QVERIFY(!toplevel->hasFocus());
+
+ toplevel->show();
+ QTest::qWaitForWindowShown(toplevel);
+ QApplication::setActiveWindow(toplevel);
+ QVERIFY(toplevel->hasFocus());
+ QVERIFY(child->hasFocus());
+
+ // verify that toggling input methods on the child widget
+ // correctly propagate to the focus proxy's input method
+ // and that the input method gets the focus proxy passed
+ // as the focus widget instead of the child widget.
+ // otherwise input method queries go to the wrong widget
+
+ QCOMPARE(inputContext->focusWidget(), toplevel);
+
+ child->setAttribute(Qt::WA_InputMethodEnabled, false);
+ QVERIFY(!inputContext->focusWidget());
+
+ child->setAttribute(Qt::WA_InputMethodEnabled, true);
+ QCOMPARE(inputContext->focusWidget(), toplevel);
+
+ child->setEnabled(false);
+ QVERIFY(!inputContext->focusWidget());
+
+ child->setEnabled(true);
+ QCOMPARE(inputContext->focusWidget(), toplevel);
+
+ delete toplevel;
+}
+
QTEST_MAIN(tst_QWidget)
#include "tst_qwidget.moc"