From 70496884450d3989829a63baac8db48d36190a25 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Wed, 6 Jan 2010 15:27:42 +0100 Subject: Fixes a crash when setting focus on a widget with a focus proxy. When the focus proxy widget doesn't have InputMethodEnabled attribute set we shouldn't try to set an input context on it. Reviewed-by: Simon Hausmann --- src/gui/kernel/qwidget.cpp | 19 ++++++++----- tests/auto/qinputcontext/tst_qinputcontext.cpp | 37 ++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 1cb3883..81a9a80 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -3088,7 +3088,8 @@ void QWidgetPrivate::setEnabled_helper(bool enable) QWidget *focusWidget = effectiveFocusWidget(); QInputContext *qic = focusWidget->d_func()->inputContext(); if (enable) { - qic->setFocusWidget(focusWidget); + if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) + qic->setFocusWidget(focusWidget); } else { qic->reset(); qic->setFocusWidget(0); @@ -10357,17 +10358,22 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) #ifndef QT_NO_IM QWidget *focusWidget = d->effectiveFocusWidget(); QInputContext *ic = 0; - if (on && !internalWinId() && testAttribute(Qt::WA_InputMethodEnabled) && hasFocus()) { + if (on && !internalWinId() && hasFocus() + && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) { ic = focusWidget->d_func()->inputContext(); - ic->reset(); - ic->setFocusWidget(0); + if (ic) { + ic->reset(); + ic->setFocusWidget(0); + } } if (!qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget()) parentWidget()->d_func()->enforceNativeChildren(); if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created)) d->createWinId(); - if (ic && isEnabled()) + if (ic && isEnabled() && focusWidget->isEnabled() + && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) { ic->setFocusWidget(focusWidget); + } #endif //QT_NO_IM break; } @@ -10404,7 +10410,8 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) if (!ic && (!on || hasFocus())) ic = focusWidget->d_func()->inputContext(); if (ic) { - if (on && hasFocus() && ic->focusWidget() != focusWidget && isEnabled()) { + if (on && hasFocus() && ic->focusWidget() != focusWidget && isEnabled() + && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) { ic->setFocusWidget(focusWidget); } else if (!on && ic->focusWidget() == focusWidget) { ic->reset(); diff --git a/tests/auto/qinputcontext/tst_qinputcontext.cpp b/tests/auto/qinputcontext/tst_qinputcontext.cpp index 50f9140..644b463 100644 --- a/tests/auto/qinputcontext/tst_qinputcontext.cpp +++ b/tests/auto/qinputcontext/tst_qinputcontext.cpp @@ -68,6 +68,7 @@ private slots: void requestSoftwareInputPanel(); void closeSoftwareInputPanel(); void selections(); + void focusProxy(); }; void tst_QInputContext::maximumTextLength() @@ -248,5 +249,41 @@ void tst_QInputContext::selections() QCOMPARE(le.inputMethodQuery(Qt::ImAnchorPosition).toInt(), 5); } +void tst_QInputContext::focusProxy() +{ + QWidget toplevel(0, Qt::X11BypassWindowManagerHint); toplevel.setObjectName("toplevel"); + QWidget w(&toplevel); w.setObjectName("w"); + QWidget proxy(&w); proxy.setObjectName("proxy"); + QWidget proxy2(&w); proxy2.setObjectName("proxy2"); + w.setFocusProxy(&proxy); + w.setAttribute(Qt::WA_InputMethodEnabled); + toplevel.show(); + QApplication::setActiveWindow(&toplevel); + QTest::qWaitForWindowShown(&toplevel); + w.setFocus(); + w.setAttribute(Qt::WA_NativeWindow); // we shouldn't crash! + + proxy.setAttribute(Qt::WA_InputMethodEnabled); + proxy2.setAttribute(Qt::WA_InputMethodEnabled); + + proxy2.setFocus(); + w.setFocus(); + + QInputContext *gic = qApp->inputContext(); + QVERIFY(gic); + qDebug() << gic->focusWidget() << &proxy; + QCOMPARE(gic->focusWidget(), &proxy); + + // then change the focus proxy and check that input context is valid + QVERIFY(w.hasFocus()); + QVERIFY(proxy.hasFocus()); + QVERIFY(!proxy2.hasFocus()); + w.setFocusProxy(&proxy2); + QVERIFY(!w.hasFocus()); + QVERIFY(proxy.hasFocus()); + QVERIFY(!proxy2.hasFocus()); + QCOMPARE(gic->focusWidget(), &proxy); +} + QTEST_MAIN(tst_QInputContext) #include "tst_qinputcontext.moc" -- cgit v0.12