From e4c54b84057e55b475cc03cbfcc289e63b01e35f Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Tue, 20 Apr 2010 09:31:58 +0200 Subject: Modify setWindowState() on Symbian to create the native window earlier. The native window is used quite early in this function so as soon as we determine that this does in fact require a native window, we should create it immediately. Reviewed-by: Janne Anttila --- src/gui/kernel/qwidget_s60.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index bfa7050..690fb8d 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -1063,6 +1063,9 @@ void QWidget::setWindowState(Qt::WindowStates newstate) return; if (isWindow()) { + createWinId(); + Q_ASSERT(testAttribute(Qt::WA_WState_Created)); + const bool wasResized = testAttribute(Qt::WA_Resized); const bool wasMoved = testAttribute(Qt::WA_Moved); @@ -1100,8 +1103,6 @@ void QWidget::setWindowState(Qt::WindowStates newstate) } #endif // Q_WS_S60 - createWinId(); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); // Ensure the initial size is valid, since we store it as normalGeometry below. if (!wasResized && !isVisible()) adjustSize(); -- cgit v0.12 From 713910ac67da8ba4b96fc6fb0e350676fbd730d3 Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Tue, 20 Apr 2010 09:35:27 +0200 Subject: Don't use setGeometry() in setWindowState() on Symbian. setGeometry() has the side effect that it internally sets both the WA_Moved and WA_Resized attributes and these attributes should only be used when the application has explicitly set a size or position. When a widget is resized due to being maximized or fullscreened then we should resize the native window handle instead of calling setGeometry. Reviewed-by: Janne Anttila --- src/gui/kernel/qwidget_s60.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 690fb8d..b6a6359 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -1112,12 +1112,14 @@ void QWidget::setWindowState(Qt::WindowStates newstate) const bool cbaVisibilityHint = windowFlags() & Qt::WindowSoftkeysVisibleHint; - if (newstate & Qt::WindowFullScreen && !cbaVisibilityHint) - setGeometry(qApp->desktop()->screenGeometry(this)); - else if (newstate & Qt::WindowMaximized || ((newstate & Qt::WindowFullScreen) && cbaVisibilityHint)) - setGeometry(qApp->desktop()->availableGeometry(this)); - else + if (newstate & Qt::WindowFullScreen && !cbaVisibilityHint) { + window->SetExtentToWholeScreen(); + } else if (newstate & Qt::WindowMaximized || ((newstate & Qt::WindowFullScreen) && cbaVisibilityHint)) { + TRect maxExtent = qt_QRect2TRect(qApp->desktop()->availableGeometry(this)); + window->SetExtent(maxExtent.iTl, maxExtent.Size()); + } else { setGeometry(normalGeometry); + } //restore normal geometry top->normalGeometry = normalGeometry; -- cgit v0.12 From 199caad8812128636a76816e931d24dcd2007af6 Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Tue, 20 Apr 2010 09:59:27 +0200 Subject: Delay creation of S60 screen furniture. Previously the S60 screen furniture (Status Pane and CBA) was being constructed when QApplication was constructed. This meant that if you never created a widget, you would still get those app panes which is not what we want. This patch avoids constructing these panes in QApplication, and manually creates them later when the first window is shown in a state where they would be needed. Reviewed-by: Janne Anttila Reviewed-by: mread --- src/gui/kernel/qapplication_s60.cpp | 1 + src/gui/kernel/qsoftkeymanager_s60.cpp | 2 ++ src/gui/kernel/qwidget_s60.cpp | 36 ++++++++++++++++++++++++++++++++++ src/gui/s60framework/qs60mainappui.cpp | 12 +++--------- 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 61beb4f..41ae294 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -73,6 +73,7 @@ # endif # include # include +# include "qs60mainappui.h" #endif #include "private/qstylesheetstyle_p.h" diff --git a/src/gui/kernel/qsoftkeymanager_s60.cpp b/src/gui/kernel/qsoftkeymanager_s60.cpp index c0761f0..f656e88 100644 --- a/src/gui/kernel/qsoftkeymanager_s60.cpp +++ b/src/gui/kernel/qsoftkeymanager_s60.cpp @@ -78,6 +78,8 @@ bool QSoftKeyManagerPrivateS60::skipCbaUpdate() // Note: Cannot use IsDisplayingMenuOrDialog since CBA update can be triggered before // menu/dialog CBA is actually displayed i.e. it is being costructed. CEikButtonGroupContainer *appUiCba = S60->buttonGroupContainer(); + if (!appUiCba) + return true; // CEikButtonGroupContainer::Current returns 0 if CBA is not visible at all CEikButtonGroupContainer *currentCba = CEikButtonGroupContainer::Current(); // Check if softkey need to be update even they are not visible diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index b6a6359..5db6e70 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -488,6 +488,42 @@ void QWidgetPrivate::show_sys() QSymbianControl *id = static_cast(q->internalWinId()); +#ifdef Q_WS_S60 + // Lazily initialize the S60 screen furniture when the first window is shown. + if (!QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes) + && !S60->buttonGroupContainer() && !S60->statusPane()) { + + bool isFullscreen = q->windowState() & Qt::WindowFullScreen; + bool cbaRequested = q->windowFlags() & Qt::WindowSoftkeysVisibleHint; + + // If the window is fullscreen and has not explicitly requested that the CBA be visible + // we delay the creation even more. + if ((!isFullscreen || cbaRequested) && !q->testAttribute(Qt::WA_DontShowOnScreen)) { + + // Create the status pane and CBA here + CEikAppUi *ui = static_cast(S60->appUi()); + MEikAppUiFactory *factory = CEikonEnv::Static()->AppUiFactory(); + TRAP_IGNORE(factory->ReadAppInfoResourceL(0, ui)); + if (S60->buttonGroupContainer()) + S60->buttonGroupContainer()->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS); + + if (S60->statusPane()) { + // Hide the status pane if fullscreen OR + // Fill client area if maximized OR + // Put window below status pane unless the window has an explicit position. + if (isFullscreen) { + S60->statusPane()->MakeVisible(false); + } else if (q->windowState() & Qt::WindowMaximized) { + TRect r = static_cast(S60->appUi())->ClientRect(); + id->SetExtent(r.iTl, r.Size()); + } else if (!q->testAttribute(Qt::WA_Moved)) { + id->SetPosition(static_cast(S60->appUi())->ClientRect().iTl); + } + } + } + } +#endif + id->MakeVisible(true); if(q->isWindow()) diff --git a/src/gui/s60framework/qs60mainappui.cpp b/src/gui/s60framework/qs60mainappui.cpp index 3b5b9d3..feffc9f 100644 --- a/src/gui/s60framework/qs60mainappui.cpp +++ b/src/gui/s60framework/qs60mainappui.cpp @@ -112,16 +112,10 @@ void QS60MainAppUi::ConstructL() // ENoAppResourceFile and ENonStandardResourceFile makes UI to work without // resource files in most SDKs. S60 3rd FP1 public seems to require resource file // even these flags are defined - TInt flags = CAknAppUi::EAknEnableSkin; - if (QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes)) { - flags |= CAknAppUi::ENoScreenFurniture | CAknAppUi::ENonStandardResourceFile; - } + TInt flags = CAknAppUi::EAknEnableSkin + | CAknAppUi::ENoScreenFurniture + | CAknAppUi::ENonStandardResourceFile; BaseConstructL(flags); - - if (!QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes)) { - CEikButtonGroupContainer* nativeContainer = Cba(); - nativeContainer->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS); - } } /*! -- cgit v0.12 From 904d205b8d69b341aa8f25dbb7a7871e6f56c2ef Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Tue, 20 Apr 2010 10:09:00 +0200 Subject: Use QDesktopWidget as a status pane observer on Symbian. Now that the S60 screen furniture construction is delayed, we need to manually set the status pane observer to get notifications about changes in the size of the status pane. Using the AppUi would have been the obvious choice here, but sadly CAknAppUi (base class for QS60MainAppUi) uses private inheritance when implementing the MEikStatusPaneObserver interface. To work around this problem we make QSymbianControl implement the interface and use the instance of this class that is associated with QDesktopWidget to recevive the notifications and then call the function in the AppUi to maintain the same behavior. Reviewed-by: Janne Anttila Reviewed-by: mread --- src/gui/kernel/qapplication_s60.cpp | 8 ++++++++ src/gui/kernel/qt_s60_p.h | 3 ++- src/gui/kernel/qwidget_s60.cpp | 5 +++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 41ae294..d87cf5f 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -540,6 +540,14 @@ void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent) sendMouseEvent(receiver, type, globalPos, button, modifiers); } +#ifdef Q_WS_S60 +void QSymbianControl::HandleStatusPaneSizeChange() +{ + QS60MainAppUi *s60AppUi = static_cast(S60->appUi()); + s60AppUi->HandleStatusPaneSizeChange(); +} +#endif + void QSymbianControl::sendMouseEvent( QWidget *receiver, QEvent::Type type, diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index a714221..58da302 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -155,7 +155,7 @@ class QLongTapTimer; class QSymbianControl : public CCoeControl, public QAbstractLongTapObserver #ifdef Q_WS_S60 -, public MAknFadedComponent +, public MAknFadedComponent, public MEikStatusPaneObserver #endif { public: @@ -183,6 +183,7 @@ public: #ifdef Q_WS_S60 void FadeBehindPopup(bool fade){ popupFader.FadeBehindPopup( this, this, fade); } + void HandleStatusPaneSizeChange(); protected: // from MAknFadedComponent TInt CountFadedComponents() {return 1;} diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 5db6e70..cae38f5 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -508,6 +508,11 @@ void QWidgetPrivate::show_sys() S60->buttonGroupContainer()->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS); if (S60->statusPane()) { + // Use QDesktopWidget as the status pane observer to proxy for the AppUi. + // Can't use AppUi directly because it privately inherits from MEikStatusPaneObserver. + QSymbianControl *desktopControl = static_cast(QApplication::desktop()->winId()); + S60->statusPane()->SetObserver(desktopControl); + // Hide the status pane if fullscreen OR // Fill client area if maximized OR // Put window below status pane unless the window has an explicit position. -- cgit v0.12 From b1cc0f58970cc07f81671f200d13d9182dce3370 Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Tue, 20 Apr 2010 10:27:49 +0200 Subject: Tweak the 'normalGeometry' of the widget before setting it. If a widget is initially shown as maximized or fullscreen then the normal geometry is calculated before the status pane has been created. When returning to the "Normal" window state the geometry needs to be tweaked to compensate the fact that there is a status present now. This should only happen if the application has not been given an explicit position. Reviewed-by: Janne Anttila --- src/gui/kernel/qwidget_s60.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index cae38f5..7fd9289 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -1149,8 +1149,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) adjustSize(); QTLWExtra *top = d->topData(); - const QRect normalGeometry = (top->normalGeometry.width() < 0) ? geometry() : top->normalGeometry; - + QRect normalGeometry = (top->normalGeometry.width() < 0) ? geometry() : top->normalGeometry; const bool cbaVisibilityHint = windowFlags() & Qt::WindowSoftkeysVisibleHint; if (newstate & Qt::WindowFullScreen && !cbaVisibilityHint) { @@ -1159,6 +1158,16 @@ void QWidget::setWindowState(Qt::WindowStates newstate) TRect maxExtent = qt_QRect2TRect(qApp->desktop()->availableGeometry(this)); window->SetExtent(maxExtent.iTl, maxExtent.Size()); } else { +#ifdef Q_WS_S60 + // With delayed creation of S60 app panes, the normalGeometry calculated above is not + // accurate because it did not consider the status pane. This means that when returning + // normal mode after showing the status pane, the geometry would overlap so we should + // move it if it never had an explicit position. + if (!wasMoved && statusPane && visible) { + TPoint tl = static_cast(S60->appUi())->ClientRect().iTl; + normalGeometry.setTopLeft(QPoint(tl.iX, tl.iY)); + } +#endif setGeometry(normalGeometry); } -- cgit v0.12 From 4886923c5024d6d50a42cbe11893cfb2f0169a76 Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Tue, 20 Apr 2010 11:15:41 +0200 Subject: Fix window transparency on Symbian. In the create_sys() function where native handles are created, we were only looking at the "isOpaque" flag to determine if a window should be translucent or not. This is not the correct thing to do because transparency should only be granted if the application explicitly sets the Qt::WA_TranslucentBackground flag. The fix is to defer the transparency decision to s60UpdateIsOpaque() which does the right thing. Reviewed-by: Jani Hautakangas --- src/gui/kernel/qwidget_s60.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 7fd9289..c30814b 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -387,16 +387,7 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de | EPointerFilterMove | EPointerFilterDrag, 0); drawableWindow->EnableVisibilityChangeEvents(); - if (!isOpaque) { - RWindow *const window = static_cast(drawableWindow); -#ifdef Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE - window->SetSurfaceTransparency(true); -#else - const TDisplayMode displayMode = static_cast(window->SetRequiredDisplayMode(EColor16MA)); - if (window->SetTransparencyAlphaChannel() == KErrNone) - window->SetBackgroundColor(TRgb(255, 255, 255, 0)); -#endif - } + s60UpdateIsOpaque(); } q->setAttribute(Qt::WA_WState_Created); -- cgit v0.12