From a93d0d1f970689991dd113d696e922854ff9ec6a Mon Sep 17 00:00:00 2001 From: axis Date: Tue, 29 Sep 2009 12:53:32 +0200 Subject: Revert "Switched to asynchronous focus handling on Symbian." This reverts commit b6377f43410b14125a66ffd02acde69cfb6e455e. The asynchronous handling caused too many headaches with input methods, which expect the focus status to be updated immediately. This may break the test case that was originally fixed by this patch (I cannot find out which one at the moment), but that will have to be solved in a different way. Conflicts: src/corelib/kernel/qcoreevent.cpp src/corelib/kernel/qcoreevent.h src/gui/kernel/qwidget.cpp src/gui/kernel/qwidget_p.h src/gui/kernel/qwidget_s60.cpp --- src/corelib/kernel/qcoreevent.cpp | 1 - src/corelib/kernel/qcoreevent.h | 4 +--- src/gui/kernel/qapplication_s60.cpp | 18 ++++++++++++++++-- src/gui/kernel/qwidget.cpp | 6 ------ src/gui/kernel/qwidget_p.h | 3 --- src/gui/kernel/qwidget_s60.cpp | 28 ---------------------------- tests/auto/qwidget/tst_qwidget.cpp | 9 --------- 7 files changed, 17 insertions(+), 52 deletions(-) diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index 185c305..3bef0d4 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -270,7 +270,6 @@ QT_BEGIN_NAMESPACE \omitvalue NetworkReplyUpdated \omitvalue FutureCallOut \omitvalue CocoaRequestModal - \omitvalue SymbianDeferredFocusChanged \omitvalue UpdateSoftKeys \omitvalue NativeGesture */ diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index bc96918..be25b41 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -281,9 +281,7 @@ public: RequestSoftwareInputPanel = 199, CloseSoftwareInputPanel = 200, - SymbianDeferredFocusChanged = 201, // Internal for generating asynchronous focus events on Symbian - - UpdateSoftKeys = 202, // Internal for compressing soft key updates + UpdateSoftKeys = 201, // Internal for compressing soft key updates // 512 reserved for Qt Jambi's MetaCall event // 513 reserved for Qt Jambi's DeleteOnMainThread event diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 0650f6c..498b1e7 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -845,8 +845,22 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) || (qwidget->windowType() & Qt::Popup) == Qt::Popup) return; - QEvent *deferredFocusEvent = new QEvent(QEvent::SymbianDeferredFocusChanged); - QApplication::postEvent(qwidget, deferredFocusEvent); + if (IsFocused()) { + QApplication::setActiveWindow(qwidget); +#ifdef Q_WS_S60 + // If widget is fullscreen, hide status pane and button container + // otherwise show them. + CEikStatusPane* statusPane = S60->statusPane(); + CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer(); + bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen; + if (statusPane && (statusPane->IsVisible() == isFullscreen)) + statusPane->MakeVisible(!isFullscreen); + if (buttonGroup && (buttonGroup->IsVisible() == isFullscreen)) + buttonGroup->MakeVisible(!isFullscreen); +#endif + } else { + QApplication::setActiveWindow(0); + } } void QSymbianControl::HandleResourceChange(int resourceType) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 08fe5b9..45b0dac 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -8336,12 +8336,6 @@ bool QWidget::event(QEvent *event) (void) QApplication::sendEvent(this, &mouseEvent); break; } - case QEvent::SymbianDeferredFocusChanged: { -#ifdef Q_OS_SYMBIAN - d->handleSymbianDeferredFocusChanged(); -#endif - break; - } #ifndef QT_NO_PROPERTIES case QEvent::DynamicPropertyChange: { const QByteArray &propName = static_cast(event)->propertyName(); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 296c5b1..15f316d 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -286,9 +286,6 @@ public: QPalette naturalWidgetPalette(uint inheritedMask) const; void setMask_sys(const QRegion &); -#ifdef Q_OS_SYMBIAN - void handleSymbianDeferredFocusChanged(); -#endif void raise_sys(); void lower_sys(); diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 6b5e9b7..f64263b 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -367,34 +367,6 @@ void QWidgetPrivate::setFocus_sys() q->effectiveWinId()->SetFocus(true); } -void QWidgetPrivate::handleSymbianDeferredFocusChanged() -{ - Q_Q(QWidget); - WId control = q->internalWinId(); - if (!control) { - // This could happen if the widget was reparented, while the focuschange - // was in the event queue. - return; - } - - if (control->IsFocused()) { - QApplication::setActiveWindow(q); -#ifdef Q_WS_S60 - // If widget is fullscreen, hide status pane and button container - // otherwise show them. - CEikStatusPane* statusPane = S60->statusPane(); - CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer(); - bool isFullscreen = q->windowState() & Qt::WindowFullScreen; - if (statusPane && (statusPane->IsVisible() == isFullscreen)) - statusPane->MakeVisible(!isFullscreen); - if (buttonGroup && (buttonGroup->IsVisible() == isFullscreen)) - buttonGroup->MakeVisible(!isFullscreen); -#endif - } else { - QApplication::setActiveWindow(0); - } -} - void QWidgetPrivate::raise_sys() { Q_Q(QWidget); diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 4cf9e8f..3918eff 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -6151,9 +6151,6 @@ void tst_QWidget::compatibilityChildInsertedEvents() EventRecorder::EventList() << qMakePair(&widget, QEvent::PolishRequest) << qMakePair(&widget, QEvent::Type(QEvent::User + 1)) -#ifdef Q_OS_SYMBIAN - << qMakePair(&widget, QEvent::SymbianDeferredFocusChanged) -#endif #if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_WS_QWS) || defined(Q_WS_S60) << qMakePair(&widget, QEvent::UpdateRequest) #endif @@ -6249,9 +6246,6 @@ void tst_QWidget::compatibilityChildInsertedEvents() << qMakePair(&widget, QEvent::PolishRequest) << qMakePair(&widget, QEvent::Type(QEvent::User + 1)) << qMakePair(&widget, QEvent::Type(QEvent::User + 2)) -#ifdef Q_OS_SYMBIAN - << qMakePair(&widget, QEvent::SymbianDeferredFocusChanged) -#endif #if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_WS_QWS) || defined(Q_WS_S60) << qMakePair(&widget, QEvent::UpdateRequest) #endif @@ -6347,9 +6341,6 @@ void tst_QWidget::compatibilityChildInsertedEvents() << qMakePair(&widget, QEvent::PolishRequest) << qMakePair(&widget, QEvent::Type(QEvent::User + 1)) << qMakePair(&widget, QEvent::Type(QEvent::User + 2)) -#ifdef Q_OS_SYMBIAN - << qMakePair(&widget, QEvent::SymbianDeferredFocusChanged) -#endif #if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_WS_QWS) || defined(Q_WS_S60) << qMakePair(&widget, QEvent::UpdateRequest) #endif -- cgit v0.12 From c3cce20dd24ee110d4a8b434ea0623fd8c07ed68 Mon Sep 17 00:00:00 2001 From: axis Date: Wed, 30 Sep 2009 10:27:15 +0200 Subject: Helped out the Symbian compiler to avoid build error. RevBy: Trust me --- tests/auto/qwidget/tst_qwidget.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 3918eff..8860924 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -5500,14 +5500,14 @@ void tst_QWidget::multipleToplevelFocusCheck() w1.activateWindow(); QApplication::setActiveWindow(&w1); QApplication::processEvents(); - QTRY_COMPARE(QApplication::activeWindow(), &w1); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&w1)); QTest::mouseDClick(&w1, Qt::LeftButton); QTRY_COMPARE(QApplication::focusWidget(), static_cast(w1.edit)); w2.activateWindow(); QApplication::setActiveWindow(&w2); QApplication::processEvents(); - QTRY_COMPARE(QApplication::activeWindow(), &w2); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&w2)); QTest::mouseClick(&w2, Qt::LeftButton); #ifdef Q_WS_QWS QEXPECT_FAIL("", "embedded toplevels take focus anyway", Continue); @@ -5520,14 +5520,14 @@ void tst_QWidget::multipleToplevelFocusCheck() w1.activateWindow(); QApplication::setActiveWindow(&w1); QApplication::processEvents(); - QTRY_COMPARE(QApplication::activeWindow(), &w1); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&w1)); QTest::mouseDClick(&w1, Qt::LeftButton); QTRY_COMPARE(QApplication::focusWidget(), static_cast(w1.edit)); w2.activateWindow(); QApplication::setActiveWindow(&w2); QApplication::processEvents(); - QTRY_COMPARE(QApplication::activeWindow(), &w2); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&w2)); QTest::mouseClick(&w2, Qt::LeftButton); QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0); } -- cgit v0.12 From 0728fa73b83e7f29990eae2520f0994e413264c2 Mon Sep 17 00:00:00 2001 From: axis Date: Wed, 30 Sep 2009 11:21:41 +0200 Subject: Avoided qt3support constructor (S60 port doesn't have it). RevBy: Paul Olav Tvete --- tests/auto/qwidget/tst_qwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 8860924..309b818 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -9146,7 +9146,7 @@ void tst_QWidget::destroyBackingStore() void tst_QWidget::rectOutsideCoordinatesLimit_task144779() { QApplication::setOverrideCursor(Qt::BlankCursor); //keep the cursor out of screen grabs - QWidget main(0,0,Qt::FramelessWindowHint); //don't get confused by the size of the window frame + QWidget main(0,Qt::FramelessWindowHint); //don't get confused by the size of the window frame QPalette palette; palette.setColor(QPalette::Window, Qt::red); main.setPalette(palette); -- cgit v0.12 From 8c4b3937511c8e960f9c03f1c711005aef49d982 Mon Sep 17 00:00:00 2001 From: axis Date: Wed, 30 Sep 2009 11:34:55 +0200 Subject: Fixed some uncommon codepaths to compile. RevBy: Trust me --- src/corelib/io/qfsfileengine_unix.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 4ec5772..114da3b 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -595,7 +595,7 @@ QString QFSFileEngine::rootPath() return QDir::cleanPath(QDir::fromNativeSeparators(qt_TDesC2QString(symbianPath))); # else # warning No fallback implementation of QFSFileEngine::rootPath() - return QLatin1String(); + return QString(); # endif #else return QLatin1String("/"); @@ -614,7 +614,7 @@ QString QFSFileEngine::tempPath() QT_MKDIR(QFile::encodeName(temp), 0777); # else # warning No fallback implementation of QFSFileEngine::tempPath() - return QString(); + QString temp; # endif #else QString temp = QFile::decodeName(qgetenv("TMPDIR")); -- cgit v0.12 From 5dadf715a40189c94235e8445dc79f0270b0a87e Mon Sep 17 00:00:00 2001 From: axis Date: Wed, 30 Sep 2009 11:41:09 +0200 Subject: Fixed some focus issues on Symbian. There are really two bugs that are fixed in this commit: - SetFocus() in Symbian does not automatically clear focus on the previously focused control, so we have to remember that control and clear it ourselves. - Symbian assumes that it is always the control at the top of the control stack that should have focus, and if this isn't the case, focus may or may not work depending on whether Symbian has had a chance to reset the focus or not. Therefore, whenever we change focus on a control, we have to also readd that control to the top of the stack, to ensure that it stays focused. RevBy: Janne Anttila --- src/gui/kernel/qapplication_s60.cpp | 35 ++++++++++++++++++++++++++++++++--- src/gui/kernel/qt_s60_p.h | 5 +++++ src/gui/kernel/qwidget_s60.cpp | 36 +++++++++++++++++++++--------------- 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 498b1e7..1e78079 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -91,6 +91,8 @@ extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp QWidget *qt_button_down = 0; // widget got last button-down +QSymbianControl *QSymbianControl::lastFocusedControl = 0; + QS60Data* qGlobalS60Data() { return qt_s60Data(); @@ -337,6 +339,7 @@ QSymbianControl::~QSymbianControl() { if (S60->curWin == this) S60->curWin = 0; + setFocusSafely(false); S60->appUi()->RemoveFromStack(this); delete m_longTapDetector; } @@ -845,8 +848,8 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) || (qwidget->windowType() & Qt::Popup) == Qt::Popup) return; - if (IsFocused()) { - QApplication::setActiveWindow(qwidget); + if (IsFocused() && IsVisible()) { + QApplication::setActiveWindow(qwidget->window()); #ifdef Q_WS_S60 // If widget is fullscreen, hide status pane and button container // otherwise show them. @@ -858,9 +861,10 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) if (buttonGroup && (buttonGroup->IsVisible() == isFullscreen)) buttonGroup->MakeVisible(!isFullscreen); #endif - } else { + } else if (QApplication::activeWindow() == qwidget->window()) { QApplication::setActiveWindow(0); } + // else { We don't touch the active window unless we were explicitly activated or deactivated } } void QSymbianControl::HandleResourceChange(int resourceType) @@ -904,6 +908,31 @@ TTypeUid::Ptr QSymbianControl::MopSupplyObject(TTypeUid id) return CCoeControl::MopSupplyObject(id); } +void QSymbianControl::setFocusSafely(bool focus) +{ + // The stack hack in here is very unfortunate, but it is the only way to ensure proper + // focus in Symbian. If this is not executed, the control which happens to be on + // the top of the stack may randomly be assigned focus by Symbian, for example + // when creating new windows (specifically in CCoeAppUi::HandleStackChanged()). + if (focus) { + S60->appUi()->RemoveFromStack(this); + // Symbian doesn't automatically remove focus from the last focused control, so we need to + // remember it and clear focus ourselves. + if (lastFocusedControl && lastFocusedControl != this) + lastFocusedControl->SetFocus(false); + QT_TRAP_THROWING(S60->appUi()->AddToStackL(this, + ECoeStackPriorityDefault + 1, ECoeStackFlagStandard)); // Note the + 1 + lastFocusedControl = this; + this->SetFocus(true); + } else { + S60->appUi()->RemoveFromStack(this); + QT_TRAP_THROWING(S60->appUi()->AddToStackL(this, + ECoeStackPriorityDefault, ECoeStackFlagStandard)); + lastFocusedControl = 0; + this->SetFocus(false); + } +} + /*! \typedef QApplication::QS60MainApplicationFactory diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 0d48634..92e695f 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -157,6 +157,8 @@ public: void setIgnoreFocusChanged(bool enabled) { m_ignoreFocusChanged = enabled; } void CancelLongTapTimer(); + void setFocusSafely(bool focus); + protected: void Draw(const TRect& aRect) const; void SizeChanged(); @@ -174,6 +176,9 @@ private: #endif private: + static QSymbianControl *lastFocusedControl; + +private: QWidget *qwidget; bool m_ignoreFocusChanged; QLongTapTimer* m_longTapDetector; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index f64263b..699f778 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -251,7 +251,10 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de } else { stackingFlags = ECoeStackFlagStandard; } + control->MakeVisible(false); QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control, ECoeStackPriorityDefault, stackingFlags)); + // Avoid keyboard focus to a hidden window. + control->setFocusSafely(false); QTLWExtra *topExtra = topData(); topExtra->rwindow = control->DrawableWindow(); @@ -284,7 +287,10 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de } else { stackingFlags = ECoeStackFlagStandard; } + control->MakeVisible(false); QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control, ECoeStackPriorityDefault, stackingFlags)); + // Avoid keyboard focus to a hidden window. + control->setFocusSafely(false); WId parentw = parentWidget->effectiveWinId(); QT_TRAP_THROWING(control->SetContainerWindowL(*parentw)); @@ -323,13 +329,13 @@ void QWidgetPrivate::show_sys() if (q->isWindow() && q->internalWinId()) { - WId id = q->internalWinId(); + QSymbianControl *id = static_cast(q->internalWinId()); if (!extra->topextra->activated) { QT_TRAP_THROWING(id->ActivateL()); extra->topextra->activated = 1; } id->MakeVisible(true); - id->SetFocus(true); + id->setFocusSafely(true); // Force setting of the icon after window is made visible, // this is needed even WA_SetWindowIcon is not set, as in that case we need @@ -345,10 +351,10 @@ void QWidgetPrivate::hide_sys() Q_Q(QWidget); Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); deactivateWidgetCleanup(); - WId id = q->internalWinId(); + QSymbianControl *id = static_cast(q->internalWinId()); if (q->isWindow() && id) { if (id->IsFocused()) // Avoid unnecessary calls to FocusChanged() - id->SetFocus(false); + id->setFocusSafely(false); id->MakeVisible(false); if (QWidgetBackingStore *bs = maybeBackingStore()) bs->releaseBuffer(); @@ -364,7 +370,7 @@ void QWidgetPrivate::setFocus_sys() Q_Q(QWidget); if (q->testAttribute(Qt::WA_WState_Created) && q->window()->windowType() != Qt::Popup) if (!q->effectiveWinId()->IsFocused()) // Avoid unnecessry calls to FocusChanged() - q->effectiveWinId()->SetFocus(true); + static_cast(q->effectiveWinId())->setFocusSafely(true); } void QWidgetPrivate::raise_sys() @@ -447,7 +453,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) if (q->testAttribute(Qt::WA_DropSiteRegistered)) q->setAttribute(Qt::WA_DropSiteRegistered, false); - WId old_winid = wasCreated ? data.winid : 0; + QSymbianControl *old_winid = static_cast(wasCreated ? data.winid : 0); if ((q->windowType() == Qt::Desktop)) old_winid = 0; setWinId(0); @@ -457,7 +463,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) if (wasCreated && old_winid) { old_winid->MakeVisible(false); if (old_winid->IsFocused()) // Avoid unnecessary calls to FocusChanged() - old_winid->SetFocus(false); + old_winid->setFocusSafely(false); old_winid->SetParent(0); } @@ -974,17 +980,17 @@ void QWidget::setWindowState(Qt::WindowStates newstate) if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) { if (newstate & Qt::WindowMinimized) { if (isVisible()) { - WId id = effectiveWinId(); + QSymbianControl *id = static_cast(effectiveWinId()); if (id->IsFocused()) // Avoid unnecessary calls to FocusChanged() - id->SetFocus(false); + id->setFocusSafely(false); id->MakeVisible(false); } } else { if (isVisible()) { - WId id = effectiveWinId(); + QSymbianControl *id = static_cast(effectiveWinId()); id->MakeVisible(true); if (!id->IsFocused()) // Avoid unnecessary calls to FocusChanged() - id->SetFocus(true); + id->setFocusSafely(true); } const QRect normalGeometry = geometry(); const QRect r = top->normalGeometry; @@ -1011,7 +1017,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) if (!isWindow() && parentWidget()) parentWidget()->d_func()->invalidateBuffer(geometry()); d->deactivateWidgetCleanup(); - WId id = internalWinId(); + QSymbianControl *id = static_cast(internalWinId()); if (testAttribute(Qt::WA_WState_Created)) { #ifndef QT_NO_IM @@ -1039,7 +1045,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) } if (destroyWindow && !(windowType() == Qt::Desktop) && id) { if (id->IsFocused()) // Avoid unnecessry calls to FocusChanged() - id->SetFocus(false); + id->setFocusSafely(false); id->ControlEnv()->AppUi()->RemoveFromStack(id); // Hack to activate window under destroyed one. With this activation @@ -1148,8 +1154,8 @@ void QWidget::activateWindow() QWidget *tlw = window(); if (tlw->isVisible()) { window()->createWinId(); - WId id = tlw->internalWinId(); - id->SetFocus(true); + QSymbianControl *id = static_cast(tlw->internalWinId()); + id->setFocusSafely(true); } } -- cgit v0.12