diff options
Diffstat (limited to 'src/gui/kernel/qapplication_s60.cpp')
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 103 |
1 files changed, 86 insertions, 17 deletions
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 0637652..d50e7e1 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(); @@ -320,13 +322,26 @@ QSymbianControl::QSymbianControl(QWidget *w) { } -void QSymbianControl::ConstructL(bool topLevel, bool desktop) +void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) { if (!desktop) { - if (topLevel) { + if (isWindowOwning or !qwidget->parentWidget()) CreateWindowL(S60->windowGroup()); - } + else + /** + * TODO: in order to avoid creating windows for all ancestors of + * this widget up to the root window, the parameter passed to + * CreateWindowL should be + * qwidget->parentWidget()->effectiveWinId(). However, if we do + * this, then we need to take care of re-parenting when a window + * is created for a widget between this one and the root window. + */ + CreateWindowL(qwidget->parentWidget()->winId()); + + // Necessary in order to be able to track the activation status of + // the control's window + qwidget->d_func()->createExtra(); SetFocusing(true); m_longTapDetector = QLongTapTimer::NewL(this); @@ -337,6 +352,7 @@ QSymbianControl::~QSymbianControl() { if (S60->curWin == this) S60->curWin = 0; + setFocusSafely(false); S60->appUi()->RemoveFromStack(this); delete m_longTapDetector; } @@ -767,19 +783,21 @@ TCoeInputCapabilities QSymbianControl::InputCapabilities() const void QSymbianControl::Draw(const TRect& r) const { QWindowSurface *surface = qwidget->windowSurface(); - if (!surface) - return; + QPaintEngine *engine = surface ? surface->paintDevice()->paintEngine() : NULL; - QPaintEngine *engine = surface->paintDevice()->paintEngine(); if (!engine) return; + if (engine->type() == QPaintEngine::Raster) { QS60WindowSurface *s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface()); CFbsBitmap *bitmap = s60Surface->symbianBitmap(); CWindowGc &gc = SystemGc(); - if (qwidget->d_func()->isOpaque) - gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); - gc.BitBlt(r.iTl, bitmap, r); + + if(!qwidget->d_func()->extraData()->disableBlit) { + if (qwidget->d_func()->isOpaque) + gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); + gc.BitBlt(r.iTl, bitmap, r); + } } else { surface->flush(qwidget, QRegion(qt_TRect2QRect(r)), QPoint()); } @@ -845,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) @@ -890,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 @@ -1027,6 +1085,10 @@ void qt_init(QApplicationPrivate * /* priv */, int) } #endif + QFont systemFont; + systemFont.setFamily(systemFont.defaultFamily()); + QApplicationPrivate::setSystemFont(systemFont); + /* ### Commented out for now as parameter handling not needed in SOS(yet). Code below will break testlib with -o flag int argc = priv->argc; @@ -1236,14 +1298,14 @@ QWidget * QApplication::topLevelAt(QPoint const& point) if (widget->geometry().adjusted(0,0,1,1).contains(point)) { // At this point we know there is a Qt widget under the point. // Now we need to make sure it is the top most in the z-order. - RDrawableWindow* rw = widget->d_func()->topData()->rwindow; - int z = rw->OrdinalPosition(); + RDrawableWindow *const window = widget->effectiveWinId()->DrawableWindow(); + int z = window->OrdinalPosition(); if (z < lowestZ) { lowestZ = z; found = widget; } } - } + } } return found; } @@ -1457,12 +1519,19 @@ bool QApplication::s60EventFilter(TWsEvent * /* aEvent */) */ void QApplication::symbianHandleCommand(int command) { + QScopedLoopLevelCounter counter(d_func()->threadData); switch (command) { - case EEikCmdExit: #ifdef Q_WS_S60 - case EAknSoftkeyExit: + case EAknSoftkeyExit: { + QCloseEvent ev; + QApplication::sendSpontaneousEvent(this, &ev); + if (ev.isAccepted()) + quit(); + break; + } #endif - exit(); + case EEikCmdExit: + quit(); break; default: bool handled = QSoftKeyManager::handleCommand(command); |