summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraxis <qt-info@nokia.com>2009-09-30 14:22:38 (GMT)
committeraxis <qt-info@nokia.com>2009-09-30 14:22:38 (GMT)
commitd4d02daeb0bea195f3ed045cfbbfe7e604420f10 (patch)
tree270eda2164f38afcdaa485bdc4935a4ed8eea9fe
parent68f709fb180af94af259a9afb873b9548c97c0fb (diff)
parent5dadf715a40189c94235e8445dc79f0270b0a87e (diff)
downloadQt-d4d02daeb0bea195f3ed045cfbbfe7e604420f10.zip
Qt-d4d02daeb0bea195f3ed045cfbbfe7e604420f10.tar.gz
Qt-d4d02daeb0bea195f3ed045cfbbfe7e604420f10.tar.bz2
Merge branch 'focusFixes' into 4.6
Conflicts: src/gui/kernel/qwidget_p.h src/gui/kernel/qwidget_s60.cpp
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp4
-rw-r--r--src/corelib/kernel/qcoreevent.cpp1
-rw-r--r--src/corelib/kernel/qcoreevent.h4
-rw-r--r--src/gui/kernel/qapplication_s60.cpp47
-rw-r--r--src/gui/kernel/qt_s60_p.h5
-rw-r--r--src/gui/kernel/qwidget.cpp6
-rw-r--r--src/gui/kernel/qwidget_p.h1
-rw-r--r--src/gui/kernel/qwidget_s60.cpp67
-rw-r--r--tests/auto/qwidget/tst_qwidget.cpp19
9 files changed, 80 insertions, 74 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"));
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 992e754..27c7c94 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();
@@ -350,6 +352,7 @@ QSymbianControl::~QSymbianControl()
{
if (S60->curWin == this)
S60->curWin = 0;
+ setFocusSafely(false);
S60->appUi()->RemoveFromStack(this);
delete m_longTapDetector;
}
@@ -860,8 +863,23 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */)
|| (qwidget->windowType() & Qt::Popup) == Qt::Popup)
return;
- QEvent *deferredFocusEvent = new QEvent(QEvent::SymbianDeferredFocusChanged);
- QApplication::postEvent(qwidget, deferredFocusEvent);
+ if (IsFocused() && IsVisible()) {
+ QApplication::setActiveWindow(qwidget->window());
+#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 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)
@@ -905,6 +923,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 d1ec74d..d33791b 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.cpp b/src/gui/kernel/qwidget.cpp
index e2de148..83593ab 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<QDynamicPropertyChangeEvent *>(event)->propertyName();
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index 2a81689..6c879be 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -293,7 +293,6 @@ public:
void setMask_sys(const QRegion &);
#ifdef Q_OS_SYMBIAN
- void handleSymbianDeferredFocusChanged();
void setSoftKeys_sys(const QList<QAction*> &softkeys);
#endif
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index d6e0a97..05db8ca 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -367,7 +367,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);
RDrawableWindow *const drawableWindow = control->DrawableWindow();
// Request mouse move events.
@@ -399,7 +402,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);
q->setAttribute(Qt::WA_WState_Created);
int x, y, w, h;
@@ -435,15 +441,15 @@ void QWidgetPrivate::show_sys()
if (q->internalWinId()) {
- WId id = q->internalWinId();
+ QSymbianControl *id = static_cast<QSymbianControl *>(q->internalWinId());
if (!extra->activated) {
QT_TRAP_THROWING(id->ActivateL());
extra->activated = 1;
}
id->MakeVisible(true);
-
+
if(q->isWindow())
- 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
@@ -461,11 +467,11 @@ void QWidgetPrivate::hide_sys()
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
deactivateWidgetCleanup();
- WId id = q->internalWinId();
+ QSymbianControl *id = static_cast<QSymbianControl *>(q->internalWinId());
if (id) {
if(id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
- id->SetFocus(false);
+ id->setFocusSafely(false);
id->MakeVisible(false);
if (QWidgetBackingStore *bs = maybeBackingStore())
bs->releaseBuffer();
@@ -481,36 +487,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);
-}
-
-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);
- }
+ static_cast<QSymbianControl *>(q->effectiveWinId())->setFocusSafely(true);
}
void QWidgetPrivate::raise_sys()
@@ -597,7 +574,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<QSymbianControl *>(wasCreated ? data.winid : 0);
if ((q->windowType() == Qt::Desktop))
old_winid = 0;
setWinId(0);
@@ -607,7 +584,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);
}
@@ -1124,17 +1101,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<QSymbianControl *>(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<QSymbianControl *>(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;
@@ -1161,7 +1138,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<QSymbianControl *>(internalWinId());
if (testAttribute(Qt::WA_WState_Created)) {
#ifndef QT_NO_IM
@@ -1189,7 +1166,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
@@ -1299,8 +1276,8 @@ void QWidget::activateWindow()
QWidget *tlw = window();
if (tlw->isVisible()) {
window()->createWinId();
- WId id = tlw->internalWinId();
- id->SetFocus(true);
+ QSymbianControl *id = static_cast<QSymbianControl *>(tlw->internalWinId());
+ id->setFocusSafely(true);
}
}
diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp
index ab7ea78..019887d 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<QWidget *>(&w1));
QTest::mouseDClick(&w1, Qt::LeftButton);
QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
w2.activateWindow();
QApplication::setActiveWindow(&w2);
QApplication::processEvents();
- QTRY_COMPARE(QApplication::activeWindow(), &w2);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&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<QWidget *>(&w1));
QTest::mouseDClick(&w1, Qt::LeftButton);
QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
w2.activateWindow();
QApplication::setActiveWindow(&w2);
QApplication::processEvents();
- QTRY_COMPARE(QApplication::activeWindow(), &w2);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
QTest::mouseClick(&w2, Qt::LeftButton);
QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
}
@@ -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
@@ -9156,7 +9147,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);