summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/kernel/qapplication_s60.cpp35
-rw-r--r--src/gui/kernel/qt_s60_p.h5
-rw-r--r--src/gui/kernel/qwidget_s60.cpp36
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<QSymbianControl *>(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<QSymbianControl *>(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<QSymbianControl *>(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<QSymbianControl *>(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<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;
@@ -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<QSymbianControl *>(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<QSymbianControl *>(tlw->internalWinId());
+ id->setFocusSafely(true);
}
}