diff options
Diffstat (limited to 'src/gui/kernel')
-rw-r--r-- | src/gui/kernel/kernel.pri | 2 | ||||
-rw-r--r-- | src/gui/kernel/qapplication.cpp | 17 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_p.h | 2 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 289 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_win.cpp | 34 | ||||
-rw-r--r-- | src/gui/kernel/qclipboard_win.cpp | 15 | ||||
-rw-r--r-- | src/gui/kernel/qcocoasharedwindowmethods_mac_p.h | 14 | ||||
-rw-r--r-- | src/gui/kernel/qdesktopwidget_s60.cpp | 14 | ||||
-rw-r--r-- | src/gui/kernel/qsoftkeymanager.cpp | 31 | ||||
-rw-r--r-- | src/gui/kernel/qsoftkeymanager_common_p.h | 3 | ||||
-rw-r--r-- | src/gui/kernel/qsoftkeymanager_s60.cpp | 12 | ||||
-rw-r--r-- | src/gui/kernel/qt_s60_p.h | 85 | ||||
-rw-r--r-- | src/gui/kernel/qwidget.cpp | 11 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_mac.mm | 14 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_p.h | 6 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_s60.cpp | 53 |
16 files changed, 511 insertions, 91 deletions
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index f9c84c1..467eb9b 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -111,6 +111,8 @@ win32 { } symbian { + exists($${EPOCROOT}epoc32/include/platform/mw/akntranseffect.h): DEFINES += QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H + SOURCES += \ kernel/qapplication_s60.cpp \ kernel/qeventdispatcher_s60.cpp \ diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 59aec91..f906bbf 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -128,6 +128,10 @@ extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp //#define ALIEN_DEBUG +#if defined(Q_OS_SYMBIAN) +#include "qt_s60_p.h" +#endif + static void initResources() { #if defined(Q_WS_WINCE) @@ -2432,6 +2436,11 @@ bool QApplication::event(QEvent *e) { Q_D(QApplication); if(e->type() == QEvent::Close) { +#if defined(Q_OS_SYMBIAN) + // In order to have proper application-exit effects on Symbian, certain + // native APIs have to be called _before_ closing/destroying the widgets. + bool effectStarted = qt_beginFullScreenEffect(); +#endif QCloseEvent *ce = static_cast<QCloseEvent*>(e); ce->accept(); closeAllWindows(); @@ -2445,8 +2454,14 @@ bool QApplication::event(QEvent *e) break; } } - if(ce->isAccepted()) + if (ce->isAccepted()) { return true; + } else { +#if defined(Q_OS_SYMBIAN) + if (effectStarted) + qt_abortFullScreenEffect(); +#endif + } } else if(e->type() == QEvent::LanguageChange) { #ifndef QT_NO_TRANSLATION setLayoutDirection(qt_detectRTLLanguage()?Qt::RightToLeft:Qt::LeftToRight); diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 43634ef..3d2c9d6 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -599,6 +599,8 @@ public: int pressureSupported; int maxTouchPressure; QList<QTouchEvent::TouchPoint> appAllTouchPoints; + + bool useTranslucentEGLSurfaces; #endif private: diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 6e43c8b..6620efd 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -100,7 +100,6 @@ static const int KGoomMemoryGoodEvent = 0x20026790; static const int KSplitViewOpenEvent = 0x2001E2C0; static const int KSplitViewCloseEvent = 0x2001E2C1; - #if defined(QT_DEBUG) static bool appNoGrab = false; // Grabbing enabled #endif @@ -143,6 +142,60 @@ void QS60Data::setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, boo // Ensure that control rectangle is updated static_cast<QSymbianControl *>(QApplication::activeWindow()->winId())->handleClientAreaChange(); } + +bool QS60Data::setRecursiveDecorationsVisibility(QWidget *window, Qt::WindowStates newState) +{ + // Show statusbar: + // Topmost parent: Show unless fullscreen/minimized. + // Child windows: Follow topmost parent, unless fullscreen, in which case do not show statusbar + // Show CBA: + // Topmost parent: Show unless fullscreen/minimized. + // Exception: Show if fullscreen with Qt::WindowSoftkeysVisibleHint. + // Child windows: + // Minimized: Unclear if there is an use case for having focused minimized window at all. + // Always follow topmost parent just to be safe. + // Maximized and normal: follow topmost parent. + // Exception: If topmost parent is not showing CBA, show CBA if any softkey actions are + // defined. + // Fullscreen: Show only if Qt::WindowSoftkeysVisibleHint set. + + Qt::WindowStates comparisonState = newState; + QWidget *parentWindow = window->parentWidget(); + if (parentWindow) { + while (parentWindow->parentWidget()) + parentWindow = parentWindow->parentWidget(); + comparisonState = parentWindow->windowState(); + } else { + parentWindow = window; + } + + bool decorationsVisible = !(comparisonState & (Qt::WindowFullScreen | Qt::WindowMinimized)); + const bool parentIsFullscreen = comparisonState & Qt::WindowFullScreen; + const bool parentCbaVisibilityHint = parentWindow->windowFlags() & Qt::WindowSoftkeysVisibleHint; + bool buttonGroupVisibility = (decorationsVisible || (parentIsFullscreen && parentCbaVisibilityHint)); + + // Do extra checking for child windows + if (window->parentWidget()) { + if (newState & Qt::WindowFullScreen) { + decorationsVisible = false; + if (window->windowFlags() & Qt::WindowSoftkeysVisibleHint) + buttonGroupVisibility = true; + else + buttonGroupVisibility = false; + } else if (!(newState & Qt::WindowMinimized) && !buttonGroupVisibility) { + for (int i = 0; i < window->actions().size(); ++i) { + if (window->actions().at(i)->softKeyRole() != QAction::NoSoftKey) { + buttonGroupVisibility = true; + break; + } + } + } + } + + S60->setStatusPaneAndButtonGroupVisibility(decorationsVisible, buttonGroupVisibility); + + return decorationsVisible; +} #endif void QS60Data::controlVisibilityChanged(CCoeControl *control, bool visible) @@ -162,6 +215,12 @@ void QS60Data::controlVisibilityChanged(CCoeControl *control, bool visible) widget->repaint(); } } else { + // In certain special scenarios we may get an ENotVisible event + // without a previous EPartiallyVisible. The backingstore must + // still be destroyed, hence the registerWidget() call below. + if (backingStore.data() && widget->internalWinId() + && qt_widget_private(widget)->maybeBackingStore() == backingStore.data()) + backingStore.registerWidget(widget); backingStore.unregisterWidget(widget); // In order to ensure that any resources used by the window surface // are immediately freed, we flush the WSERV command buffer. @@ -406,6 +465,7 @@ QSymbianControl::QSymbianControl(QWidget *w) , m_ignoreFocusChanged(0) , m_symbianPopupIsOpen(0) , m_inExternalScreenOverride(false) + , m_lastStatusPaneVisibility(0) { } @@ -492,11 +552,52 @@ void QSymbianControl::setWidget(QWidget *w) { qwidget = w; } + +QPoint QSymbianControl::translatePointForFixedNativeOrientation(const TPoint &pointerEventPos) const +{ + QPoint pos(pointerEventPos.iX, pointerEventPos.iY); + if (qwidget->d_func()->fixNativeOrientationCalled) { + QSize wsize = qwidget->size(); + TSize size = Size(); + if (size.iWidth == wsize.height() && size.iHeight == wsize.width()) { + qreal x = pos.x(); + qreal y = pos.y(); + pos.setX(size.iHeight - y); + pos.setY(x); + } + } + return pos; +} + +TRect QSymbianControl::translateRectForFixedNativeOrientation(const TRect &controlRect) const +{ + TRect rect = controlRect; + if (qwidget->d_func()->fixNativeOrientationCalled) { + QPoint a = translatePointForFixedNativeOrientation(rect.iTl); + QPoint b = translatePointForFixedNativeOrientation(rect.iBr); + if (a.x() < b.x()) { + rect.iTl.iX = a.x(); + rect.iBr.iX = b.x(); + } else { + rect.iTl.iX = b.x(); + rect.iBr.iX = a.x(); + } + if (a.y() < b.y()) { + rect.iTl.iY = a.y(); + rect.iBr.iY = b.y(); + } else { + rect.iTl.iY = b.y(); + rect.iBr.iY = a.y(); + } + } + return rect; +} + void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation ) { QWidget *alienWidget; - QPoint widgetPos = QPoint(aPenEventLocation.iX, aPenEventLocation.iY); - QPoint globalPos = QPoint(aPenEventScreenLocation.iX,aPenEventScreenLocation.iY); + QPoint widgetPos = translatePointForFixedNativeOrientation(aPenEventLocation); + QPoint globalPos = translatePointForFixedNativeOrientation(aPenEventScreenLocation); alienWidget = qwidget->childAt(widgetPos); if (!alienWidget) alienWidget = qwidget; @@ -511,7 +612,7 @@ void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, cons void QSymbianControl::translateAdvancedPointerEvent(const TAdvancedPointerEvent *event) { QApplicationPrivate *d = QApplicationPrivate::instance(); - QPointF screenPos = qwidget->mapToGlobal(QPoint(event->iPosition.iX, event->iPosition.iY)); + QPointF screenPos = qwidget->mapToGlobal(translatePointForFixedNativeOrientation(event->iPosition)); qreal pressure; if(d->pressureSupported && event->Pressure() > 0) //workaround for misconfigured HAL @@ -612,7 +713,7 @@ void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent) mapS60MouseEventTypeToQt(&type, &button, &pEvent); Qt::KeyboardModifiers modifiers = mapToQtModifiers(pEvent.iModifiers); - QPoint widgetPos = QPoint(pEvent.iPosition.iX, pEvent.iPosition.iY); + QPoint widgetPos = translatePointForFixedNativeOrientation(pEvent.iPosition); TPoint controlScreenPos = PositionRelativeToScreen(); QPoint globalPos = QPoint(controlScreenPos.iX, controlScreenPos.iY) + widgetPos; S60->lastCursorPos = globalPos; @@ -1078,6 +1179,9 @@ void QSymbianControl::Draw(const TRect& controlRect) const Q_ASSERT(window); QTLWExtra *topExtra = window->d_func()->maybeTopData(); Q_ASSERT(topExtra); + + TRect wcontrolRect = translateRectForFixedNativeOrientation(controlRect); + if (!topExtra->inExpose) { topExtra->inExpose = true; if (!qwidget->isWindow()) { @@ -1088,7 +1192,7 @@ void QSymbianControl::Draw(const TRect& controlRect) const gc.SetBrushColor(TRgb(0, 0, 0, 0)); gc.Clear(controlRect); } - QRect exposeRect = qt_TRect2QRect(controlRect); + QRect exposeRect = qt_TRect2QRect(wcontrolRect); qwidget->d_func()->syncBackingStore(exposeRect); topExtra->inExpose = false; } @@ -1101,7 +1205,7 @@ void QSymbianControl::Draw(const TRect& controlRect) const const bool sendNativePaintEvents = qwidget->d_func()->extraData()->receiveNativePaintEvents; if (sendNativePaintEvents) { - const QRect r = qt_TRect2QRect(controlRect); + const QRect r = qt_TRect2QRect(wcontrolRect); QMetaObject::invokeMethod(qwidget, "beginNativePaintEvent", Qt::DirectConnection, Q_ARG(QRect, r)); } @@ -1133,7 +1237,8 @@ void QSymbianControl::Draw(const TRect& controlRect) const // Do nothing break; case QWExtra::Blit: - if (qwidget->d_func()->isOpaque) + case QWExtra::BlitWriteAlpha: + if (qwidget->d_func()->isOpaque || nativePaintMode == QWExtra::BlitWriteAlpha) gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); gc.BitBlt(controlRect.iTl, bitmap, backingStoreRect); break; @@ -1155,7 +1260,7 @@ void QSymbianControl::Draw(const TRect& controlRect) const } if (sendNativePaintEvents) { - const QRect r = qt_TRect2QRect(controlRect); + const QRect r = qt_TRect2QRect(wcontrolRect); // The draw ops aren't actually sent to WSERV until the graphics // context is deactivated, which happens in the function calling // this one. We therefore delay the delivery of endNativePaintEvent, @@ -1168,14 +1273,45 @@ void QSymbianControl::Draw(const TRect& controlRect) const } } +void QSymbianControl::qwidgetResize_helper(const QSize &newSize) +{ + QRect cr = qwidget->geometry(); + QSize oldSize(cr.size()); + cr.setSize(newSize); + qwidget->data->crect = cr; + if (qwidget->isVisible()) { + QTLWExtra *tlwExtra = qwidget->d_func()->maybeTopData(); + bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt(); + if (!slowResize && tlwExtra) + tlwExtra->inTopLevelResize = true; + QResizeEvent e(newSize, oldSize); + qt_sendSpontaneousEvent(qwidget, &e); + if (!qwidget->testAttribute(Qt::WA_StaticContents)) + qwidget->d_func()->syncBackingStore(); + if (!slowResize && tlwExtra) + tlwExtra->inTopLevelResize = false; + } else { + if (!qwidget->testAttribute(Qt::WA_PendingResizeEvent)) { + QResizeEvent *e = new QResizeEvent(newSize, oldSize); + QApplication::postEvent(qwidget, e); + } + } +} + void QSymbianControl::SizeChanged() { CCoeControl::SizeChanged(); + // When FixNativeOrientation had been called, the RWindow/CCoeControl size + // and the surface/QWidget size have nothing to do with each other. + if (qwidget->d_func()->fixNativeOrientationCalled) + return; + QSize oldSize = qwidget->size(); QSize newSize(Size().iWidth, Size().iHeight); if (oldSize != newSize) { + // Enforce the proper size for fullscreen widgets on the secondary screen. const bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen; const int screenNumber = S60->screenNumberForWidget(qwidget); if (!m_inExternalScreenOverride && isFullscreen && screenNumber > 0) { @@ -1188,26 +1324,8 @@ void QSymbianControl::SizeChanged() return; } } - QRect cr = qwidget->geometry(); - cr.setSize(newSize); - qwidget->data->crect = cr; - if (qwidget->isVisible()) { - QTLWExtra *tlwExtra = qwidget->d_func()->maybeTopData(); - bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt(); - if (!slowResize && tlwExtra) - tlwExtra->inTopLevelResize = true; - QResizeEvent e(newSize, oldSize); - qt_sendSpontaneousEvent(qwidget, &e); - if (!qwidget->testAttribute(Qt::WA_StaticContents)) - qwidget->d_func()->syncBackingStore(); - if (!slowResize && tlwExtra) - tlwExtra->inTopLevelResize = false; - } else { - if (!qwidget->testAttribute(Qt::WA_PendingResizeEvent)) { - QResizeEvent *e = new QResizeEvent(newSize, oldSize); - QApplication::postEvent(qwidget, e); - } - } + + qwidgetResize_helper(newSize); } m_inExternalScreenOverride = false; @@ -1271,16 +1389,8 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) qwidget->d_func()->setWindowIcon_sys(true); qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle()); #ifdef Q_WS_S60 - // If widget is fullscreen/minimized, hide status pane and button container otherwise show them. - QWidget *const window = qwidget->window(); - if (!window->parentWidget()) { // Only top level native windows have control over cba/status pane - const bool decorationsVisible = !(window->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized)); - const bool statusPaneVisibility = decorationsVisible; - const bool isFullscreen = window->windowState() & Qt::WindowFullScreen; - const bool cbaVisibilityHint = window->windowFlags() & Qt::WindowSoftkeysVisibleHint; - const bool buttonGroupVisibility = (decorationsVisible || (isFullscreen && cbaVisibilityHint)); - S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility); - } + if (qwidget->isWindow()) + S60->setRecursiveDecorationsVisibility(qwidget, qwidget->windowState()); #endif } else if (QApplication::activeWindow() == qwidget->window()) { bool focusedControlFound = false; @@ -1381,7 +1491,13 @@ void QSymbianControl::HandleResourceChange(int resourceType) } break; case KInternalStatusPaneChange: - handleClientAreaChange(); + // When status pane is not visible, only handle client area change if status pane was + // previously visible, as size changes to hidden status pane should not affect + // client area. + if (S60->statusPane() && (S60->statusPane()->IsVisible() || m_lastStatusPaneVisibility)) { + m_lastStatusPaneVisibility = S60->statusPane()->IsVisible(); + handleClientAreaChange(); + } if (IsFocused() && IsVisible()) { qwidget->d_func()->setWindowIcon_sys(true); qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle()); @@ -1395,8 +1511,10 @@ void QSymbianControl::HandleResourceChange(int resourceType) { handleClientAreaChange(); // Send resize event to trigger desktopwidget workAreaResized signal - QResizeEvent e(qt_desktopWidget->size(), qt_desktopWidget->size()); - QApplication::sendEvent(qt_desktopWidget, &e); + if (qt_desktopWidget) { + QResizeEvent e(qt_desktopWidget->size(), qt_desktopWidget->size()); + QApplication::sendEvent(qt_desktopWidget, &e); + } break; } #endif @@ -1455,6 +1573,55 @@ bool QSymbianControl::isControlActive() return IsActivated() ? true : false; } +void QSymbianControl::ensureFixNativeOrientation() +{ +#if defined(Q_SYMBIAN_SUPPORTS_FIXNATIVEORIENTATION) + if (!qwidget->isWindow() || qwidget->windowType() == Qt::Desktop) + return; + if (S60->screenNumberForWidget(qwidget) > 0) + return; + const bool isFixed = qwidget->d_func()->fixNativeOrientationCalled; + const bool isFixEnabled = qwidget->testAttribute(Qt::WA_SymbianNoSystemRotation); + const bool isFullScreen = qwidget->windowState().testFlag(Qt::WindowFullScreen); + if (isFullScreen && isFixEnabled) { + const bool surfaceBasedGs = + QApplicationPrivate::graphics_system_name == QLatin1String("openvg") + || QApplicationPrivate::graphics_system_name == QLatin1String("opengl"); + if (!surfaceBasedGs) + qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false); + if (!isFixed && surfaceBasedGs) { + if (Window().FixNativeOrientation() == KErrNone) { + qwidget->d_func()->fixNativeOrientationCalled = true; + // The EGL window surface is now fixed to the native orientation + // of the device, no matter what size we pass when creating it. + // Enforce the same size for the QWidget too. For the underlying + // CCoeControl and RWindow it is up to the system to resize them + // when the standard auto-rotation mechanism is in use, we must not + // change that behavior by forcing any size for those. In practice + // this means that the QWidget and the underlying native control + // dimensions will be out of sync when FixNativeOrientation was + // called and the device is turned to the non-native (typically + // landscape) orientation. The pointer event handling and certain + // functions like Draw() will need to compensate for this. + QSize newSize(S60->nativeScreenWidthInPixels, S60->nativeScreenHeightInPixels); + if (qwidget->size() != newSize) + qwidgetResize_helper(newSize); + } else { + qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false); + } + } + } else if (isFixed) { + qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false); + qwidget->d_func()->fixNativeOrientationCalled = false; + qwidget->hide(); + qwidget->d_func()->create_sys(0, false, true); + qwidget->show(); + } +#else + qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false); +#endif +} + /*! \typedef QApplication::QS60MainApplicationFactory \since 4.6 @@ -1661,10 +1828,36 @@ void qt_init(QApplicationPrivate * /* priv */, int) systemFont.setFamily(systemFont.defaultFamily()); QApplicationPrivate::setSystemFont(systemFont); -#ifdef Q_SYMBIAN_TRANSITION_EFFECTS QObject::connect(qApp, SIGNAL(aboutToQuit()), qApp, SLOT(_q_aboutToQuit())); -#endif +#ifdef Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE + QApplicationPrivate::instance()->useTranslucentEGLSurfaces = true; + + const TUid KIvePropertyCat = {0x2726beef}; + enum TIvePropertyChipType { + EVCBCM2727B1 = 0x00000000, + EVCBCM2763A0 = 0x04000100, + EVCBCM2763B0 = 0x04000102, + EVCBCM2763C0 = 0x04000103, + EVCBCM2763C1 = 0x04000104, + EVCBCMUnknown = 0x7fffffff + }; + + TInt chipType = EVCBCMUnknown; + if (RProperty::Get(KIvePropertyCat, 0 /*chip type*/, chipType) == KErrNone) { + if (chipType == EVCBCM2727B1) { + // We have only 32MB GPU memory. Use raster surfaces + // for transparent TLWs. + QApplicationPrivate::instance()->useTranslucentEGLSurfaces = false; + } + } else { + QApplicationPrivate::instance()->useTranslucentEGLSurfaces = false; + } + if (QApplicationPrivate::graphics_system_name == QLatin1String("raster")) + QApplicationPrivate::instance()->useTranslucentEGLSurfaces = false; +#else + QApplicationPrivate::instance()->useTranslucentEGLSurfaces = false; +#endif /* ### Commented out for now as parameter handling not needed in SOS(yet). Code below will break testlib with -o flag int argc = priv->argc; @@ -1726,6 +1919,9 @@ void qt_cleanup() S60->setButtonGroupContainer(0); #endif + // Call EndFullScreen() to prevent confusing the system effect state machine. + qt_endFullScreenEffect(); + if (S60->qtOwnsS60Environment) { // Restore the S60 framework trap handler. See qt_init(). User::SetTrapHandler(S60->s60InstalledTrapHandler); @@ -2097,7 +2293,8 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent } #endif #ifdef QT_SOFTKEYS_ENABLED - QSoftKeyManager::updateSoftKeys(); + if (!CEikonEnv::Static()->EikAppUi()->IsDisplayingMenuOrDialog()) + QSoftKeyManager::updateSoftKeys(); #endif break; case EEventFocusLost: @@ -2463,6 +2660,8 @@ void QApplication::restoreOverrideCursor() void QApplicationPrivate::_q_aboutToQuit() { + qt_beginFullScreenEffect(); + #ifdef Q_SYMBIAN_TRANSITION_EFFECTS // Send the shutdown tfx command S60->wsSession().SendEffectCommand(ETfxCmdAppShutDown); diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 6e89ceb..913bc7e 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -3779,16 +3779,32 @@ bool QETWidget::translateConfigEvent(const MSG &msg) QApplication::sendSpontaneousEvent(this, &e); hideChildren(true); } - } else if (msg.wParam != SIZE_MINIMIZED && isMinimized()) { + } else if (msg.wParam != SIZE_MINIMIZED) { + bool window_state_changed = false; + Qt::WindowStates oldstate = Qt::WindowStates(dataPtr()->window_state); + if (isMinimized()) { #ifndef Q_WS_WINCE - const QString title = windowTitle(); - if (!title.isEmpty()) - d_func()->setWindowTitle_helper(title); + const QString title = windowTitle(); + if (!title.isEmpty()) + d_func()->setWindowTitle_helper(title); #endif - data->window_state &= ~Qt::WindowMinimized; - showChildren(true); - QShowEvent e; - QApplication::sendSpontaneousEvent(this, &e); + data->window_state &= ~Qt::WindowMinimized; + showChildren(true); + QShowEvent e; + QApplication::sendSpontaneousEvent(this, &e); + // Capture SIZE_MAXIMIZED and SIZE_RESTORED without preceding WM_SYSCOMMAND + // (Aero Snap on Win7) + } else if (msg.wParam == SIZE_MAXIMIZED && !isMaximized()) { + data->window_state |= Qt::WindowMaximized; + window_state_changed = true; + } else if (msg.wParam == SIZE_RESTORED && isMaximized()) { + data->window_state &= ~(Qt::WindowMaximized); + window_state_changed = true; + } + if (window_state_changed) { + QWindowStateChangeEvent e(oldstate); + QApplication::sendSpontaneousEvent(this, &e); + } } } if (msg.wParam != SIZE_MINIMIZED && oldSize != newSize) { @@ -3820,7 +3836,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg) QApplication::postEvent(this, e); } } -} else if (msg.message == WM_MOVE) { // move event + } else if (msg.message == WM_MOVE) { // move event int a = (int) (short) LOWORD(msg.lParam); int b = (int) (short) HIWORD(msg.lParam); QPoint oldPos = geometry().topLeft(); diff --git a/src/gui/kernel/qclipboard_win.cpp b/src/gui/kernel/qclipboard_win.cpp index 52b9663..ea41165 100644 --- a/src/gui/kernel/qclipboard_win.cpp +++ b/src/gui/kernel/qclipboard_win.cpp @@ -52,6 +52,7 @@ #include "qt_windows.h" #include "qdnd_p.h" #include <private/qwidget_p.h> +#include <private/qsystemlibrary_p.h> QT_BEGIN_NAMESPACE @@ -70,6 +71,9 @@ void QtCeFlushClipboard(); #endif +typedef BOOL (WINAPI *PtrIsHungAppWindow)(HWND); + +static PtrIsHungAppWindow ptrIsHungAppWindow = 0; class QClipboardWatcher : public QInternalMimeData { public: @@ -327,9 +331,16 @@ bool QClipboard::event(QEvent *e) d->releaseIData(); propagate = true; } - if (propagate && d->nextClipboardViewer) { - SendMessage(d->nextClipboardViewer, m->message, m->wParam, m->lParam); + if (ptrIsHungAppWindow == 0) { + QSystemLibrary library(QLatin1String("User32")); + ptrIsHungAppWindow = (PtrIsHungAppWindow)library.resolve("IsHungAppWindow"); + } + if (ptrIsHungAppWindow && ptrIsHungAppWindow(d->nextClipboardViewer)) { + qWarning("%s: Cowardly refusing to send clipboard message to hung application...", Q_FUNC_INFO); + } else { + SendMessage(d->nextClipboardViewer, m->message, m->wParam, m->lParam); + } } return true; diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index 6254061..406e6d4 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -157,6 +157,20 @@ QT_END_NAMESPACE [NSApp terminate:sender]; } +- (void)setLevel:(NSInteger)windowLevel +{ + // Cocoa will upon activating/deactivating applications level modal + // windows up and down, regardsless of any explicit set window level. + // To ensure that modal stays-on-top dialogs actually stays on top after + // the application is activated (and therefore stacks in front of + // other stays-on-top windows), we need to add this little special-case override: + QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; + if (widget && widget->isModal() && (widget->windowFlags() & Qt::WindowStaysOnTopHint)) + [super setLevel:NSPopUpMenuWindowLevel]; + else + [super setLevel:windowLevel]; +} + - (void)sendEvent:(NSEvent *)event { if ([event type] == NSApplicationDefined) { diff --git a/src/gui/kernel/qdesktopwidget_s60.cpp b/src/gui/kernel/qdesktopwidget_s60.cpp index c3963f4..62a4d40 100644 --- a/src/gui/kernel/qdesktopwidget_s60.cpp +++ b/src/gui/kernel/qdesktopwidget_s60.cpp @@ -188,12 +188,14 @@ void QDesktopWidgetPrivate::cleanup() void QDesktopWidgetPrivate::init_sys() { #if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) - CWsScreenDevice *dev = S60->screenDevice(1); - if (dev) { - displayControl = static_cast<MDisplayControl *>( - dev->GetInterface(MDisplayControl::ETypeId)); - if (displayControl) { - displayControl->EnableDisplayChangeEvents(ETrue); + if (S60->screenCount() > 1) { + CWsScreenDevice *dev = S60->screenDevice(1); + if (dev) { + displayControl = static_cast<MDisplayControl *>( + dev->GetInterface(MDisplayControl::ETypeId)); + if (displayControl) { + displayControl->EnableDisplayChangeEvents(ETrue); + } } } #endif diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp index 1b26933..204efe9 100644 --- a/src/gui/kernel/qsoftkeymanager.cpp +++ b/src/gui/kernel/qsoftkeymanager.cpp @@ -50,6 +50,10 @@ #include "private/qsoftkeymanager_s60_p.h" #endif +#ifdef SYMBIAN_VERSION_SYMBIAN3 +#include "private/qt_s60_p.h" +#endif + #ifndef QT_NO_SOFTKEYMANAGER QT_BEGIN_NAMESPACE @@ -101,6 +105,30 @@ QSoftKeyManager::QSoftKeyManager() : QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *actionWidget) { QAction *action = new QAction(standardSoftKeyText(standardKey), actionWidget); +#ifdef SYMBIAN_VERSION_SYMBIAN3 + int key = 0; + switch (standardKey) { + case OkSoftKey: + key = EAknSoftkeyOk; + break; + case SelectSoftKey: + key = EAknSoftkeySelect; + break; + case DoneSoftKey: + key = EAknSoftkeyDone; + break; + case MenuSoftKey: + key = EAknSoftkeyOptions; + break; + case CancelSoftKey: + key = EAknSoftkeyCancel; + break; + default: + break; + }; + if (key != 0) + QSoftKeyManager::instance()->d_func()->softKeyCommandActions.insert(action, key); +#endif QAction::SoftKeyRole softKeyRole = QAction::NoSoftKey; switch (standardKey) { case MenuSoftKey: // FALL-THROUGH @@ -143,6 +171,9 @@ void QSoftKeyManager::cleanupHash(QObject *obj) Q_D(QSoftKeyManager); QAction *action = qobject_cast<QAction*>(obj); d->keyedActions.remove(action); +#ifdef SYMBIAN_VERSION_SYMBIAN3 + d->softKeyCommandActions.remove(action); +#endif } void QSoftKeyManager::sendKeyEvent() diff --git a/src/gui/kernel/qsoftkeymanager_common_p.h b/src/gui/kernel/qsoftkeymanager_common_p.h index 27d8ee9..02ae697 100644 --- a/src/gui/kernel/qsoftkeymanager_common_p.h +++ b/src/gui/kernel/qsoftkeymanager_common_p.h @@ -72,6 +72,9 @@ protected: QMultiHash<int, QAction*> requestedSoftKeyActions; QWidget *initialSoftKeySource; bool pendingUpdate; +#ifdef SYMBIAN_VERSION_SYMBIAN3 + QHash<QAction*, int> softKeyCommandActions; +#endif }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qsoftkeymanager_s60.cpp b/src/gui/kernel/qsoftkeymanager_s60.cpp index 3496297..79ed91a 100644 --- a/src/gui/kernel/qsoftkeymanager_s60.cpp +++ b/src/gui/kernel/qsoftkeymanager_s60.cpp @@ -113,12 +113,20 @@ void QSoftKeyManagerPrivateS60::ensureCbaVisibilityAndResponsiviness(CEikButtonG void QSoftKeyManagerPrivateS60::clearSoftkeys(CEikButtonGroupContainer &cba) { +#ifdef SYMBIAN_VERSION_SYMBIAN3 + QT_TRAP_THROWING( + //EAknSoftkeyEmpty is used, because using -1 adds softkeys without actions on Symbian3 + cba.SetCommandL(0, EAknSoftkeyEmpty, KNullDesC); + cba.SetCommandL(2, EAknSoftkeyEmpty, KNullDesC); + ); +#else QT_TRAP_THROWING( //Using -1 instead of EAknSoftkeyEmpty to avoid flickering. cba.SetCommandL(0, -1, KNullDesC); // TODO: Should we clear also middle SK? cba.SetCommandL(2, -1, KNullDesC); ); +#endif realSoftKeyActions.clear(); } @@ -290,6 +298,10 @@ bool QSoftKeyManagerPrivateS60::setSoftkey(CEikButtonGroupContainer &cba, QString text = softkeyText(*action); TPtrC nativeText = qt_QString2TPtrC(text); int command = S60_COMMAND_START + position; +#ifdef SYMBIAN_VERSION_SYMBIAN3 + if (softKeyCommandActions.contains(action)) + command = softKeyCommandActions.value(action); +#endif setNativeSoftkey(cba, position, command, nativeText); const bool dimmed = !action->isEnabled() && !QSoftKeyManager::isForceEnabledInSofkeys(action); cba.DimCommand(command, dimmed); diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 3bb27c3..8aba53a 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -77,6 +77,10 @@ #include <akncontext.h> // CAknContextPane #include <eikspane.h> // CEikStatusPane #include <AknPopupFader.h> // MAknFadedComponent and TAknPopupFader +#include <gfxtranseffect/gfxtranseffect.h> // BeginFullScreen +#ifdef QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H +#include <akntranseffect.h> // BeginFullScreen +#endif #endif QT_BEGIN_NAMESPACE @@ -85,6 +89,9 @@ QT_BEGIN_NAMESPACE // system events seems to start with 0x10 const TInt KInternalStatusPaneChange = 0x50000000; +// For BeginFullScreen(). +const TUint KQtAppExitFlag = 0x400; + static const int qt_symbian_max_screens = 4; //this macro exists because EColor16MAP enum value doesn't exist in Symbian OS 9.2 @@ -178,6 +185,7 @@ public: static inline CEikButtonGroupContainer* buttonGroupContainer(); static inline void setButtonGroupContainer(CEikButtonGroupContainer* newCba); static void setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, bool buttonGroupVisible); + static bool setRecursiveDecorationsVisibility(QWidget *window, Qt::WindowStates newState); #endif static void controlVisibilityChanged(CCoeControl *control, bool visible); @@ -189,6 +197,12 @@ public: int screenHeightInPixelsForScreen[qt_symbian_max_screens]; int screenWidthInTwipsForScreen[qt_symbian_max_screens]; int screenHeightInTwipsForScreen[qt_symbian_max_screens]; + + int nativeScreenWidthInPixels; + int nativeScreenHeightInPixels; + + int beginFullScreenCalled : 1; + int endFullScreenCalled : 1; }; Q_AUTOTEST_EXPORT QS60Data* qGlobalS60Data(); @@ -233,6 +247,10 @@ public: bool isControlActive(); + void ensureFixNativeOrientation(); + QPoint translatePointForFixedNativeOrientation(const TPoint &pointerEventPos) const; + TRect translateRectForFixedNativeOrientation(const TRect &controlRect) const; + #ifdef Q_WS_S60 void FadeBehindPopup(bool fade){ popupFader.FadeBehindPopup( this, this, fade); } void HandleStatusPaneSizeChange(); @@ -251,6 +269,9 @@ protected: void PositionChanged(); void FocusChanged(TDrawNow aDrawNow); +protected: + void qwidgetResize_helper(const QSize &newSize); + private: void HandlePointerEvent(const TPointerEvent& aPointerEvent); TKeyResponse OfferKeyEvent(const TKeyEvent& aKeyEvent,TEventCode aType); @@ -290,6 +311,7 @@ private: #endif bool m_inExternalScreenOverride : 1; + bool m_lastStatusPaneVisibility : 1; }; inline QS60Data::QS60Data() @@ -322,14 +344,18 @@ inline QS60Data::QS60Data() #ifdef Q_OS_SYMBIAN ,s60InstalledTrapHandler(0) #endif + ,beginFullScreenCalled(0), + endFullScreenCalled(0) { } inline void QS60Data::updateScreenSize() { + CWsScreenDevice *dev = S60->screenDevice(); + int screenModeCount = dev->NumScreenModes(); + int mode = dev->CurrentScreenMode(); TPixelsTwipsAndRotation params; - int mode = S60->screenDevice()->CurrentScreenMode(); - S60->screenDevice()->GetScreenModeSizeAndRotation(mode, params); + dev->GetScreenModeSizeAndRotation(mode, params); S60->screenWidthInPixels = params.iPixelSize.iWidth; S60->screenHeightInPixels = params.iPixelSize.iHeight; S60->screenWidthInTwips = params.iTwipsSize.iWidth; @@ -352,6 +378,18 @@ inline void QS60Data::updateScreenSize() S60->screenWidthInTwipsForScreen[i] = params.iTwipsSize.iWidth; S60->screenHeightInTwipsForScreen[i] = params.iTwipsSize.iHeight; } + + // Look for a screen mode with rotation 0 + // in order to decide what the native orientation is. + for (mode = 0; mode < screenModeCount; ++mode) { + TPixelsAndRotation sizeAndRotation; + dev->GetScreenModeSizeAndRotation(mode, sizeAndRotation); + if (sizeAndRotation.iRotation == CFbsBitGc::EGraphicsOrientationNormal) { + S60->nativeScreenWidthInPixels = sizeAndRotation.iPixelSize.iWidth; + S60->nativeScreenHeightInPixels = sizeAndRotation.iPixelSize.iHeight; + break; + } + } } inline RWsSession& QS60Data::wsSession() @@ -539,6 +577,49 @@ void qt_symbian_set_cursor_visible(bool visible); bool qt_symbian_is_cursor_visible(); #endif +static inline bool qt_beginFullScreenEffect() +{ +#if defined(Q_WS_S60) && defined(QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H) + // Only for post-S^3. On earlier versions the system transition effects + // may not be able to capture the non-Avkon content, leading to confusing + // looking effects, so just skip the whole thing. + if (S60->beginFullScreenCalled || QSysInfo::s60Version() <= QSysInfo::SV_S60_5_2) + return false; + S60->beginFullScreenCalled = true; + // For Avkon apps the app-exit effect is triggered from CAknAppUi::PrepareToExit(). + // That is good for Avkon apps, but in case of Qt the RWindows are destroyed earlier. + // Therefore we call BeginFullScreen() ourselves. + GfxTransEffect::BeginFullScreen(AknTransEffect::EApplicationExit, + TRect(0, 0, 0, 0), + AknTransEffect::EParameterType, + AknTransEffect::GfxTransParam(S60->uid, + AknTransEffect::TParameter::EAvkonCheck | KQtAppExitFlag)); + return true; +#else + return false; +#endif +} + +static inline void qt_abortFullScreenEffect() +{ +#if defined(Q_WS_S60) && defined(QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H) + if (!S60->beginFullScreenCalled || QSysInfo::s60Version() <= QSysInfo::SV_S60_5_2) + return; + GfxTransEffect::AbortFullScreen(); + S60->beginFullScreenCalled = S60->endFullScreenCalled = false; +#endif +} + +static inline void qt_endFullScreenEffect() +{ +#if defined(Q_WS_S60) && defined(QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H) + if (S60->endFullScreenCalled || QSysInfo::s60Version() <= QSysInfo::SV_S60_5_2) + return; + S60->endFullScreenCalled = true; + GfxTransEffect::EndFullScreen(); +#endif +} + QT_END_NAMESPACE #endif // QT_S60_P_H diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 1786e65..ac35d42 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -306,6 +306,7 @@ QWidgetPrivate::QWidgetPrivate(int version) , qd_hd(0) #elif defined(Q_OS_SYMBIAN) , symbianScreenNumber(0) + , fixNativeOrientationCalled(false) #endif { if (!qApp) { @@ -597,8 +598,7 @@ void QWidget::setAutoFillBackground(bool enabled) \brief The QWidget class is the base class of all user interface objects. \ingroup basicwidgets - - + The widget is the atom of the user interface: it receives mouse, keyboard and other events from the window system, and paints a representation of itself on the screen. Every widget is rectangular, and they are sorted in a @@ -1326,8 +1326,8 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) //give potential windows a bigger "pre-initial" size; create_sys() will give them a new size later #ifdef Q_OS_SYMBIAN if (isGLWidget) { - // Don't waste GPU mem for unnecessary large egl surface - data.crect = QRect(0,0,2,2); + // Don't waste GPU mem for unnecessary large egl surface until resized by application + data.crect = QRect(0,0,1,1); } else { data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,360,640); } @@ -10866,6 +10866,9 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) } QT_TRAP_THROWING(appUi->SetOrientationL(s60orientation)); S60->orientationSet = true; + QSymbianControl *window = static_cast<QSymbianControl *>(internalWinId()); + if (window) + window->ensureFixNativeOrientation(); #endif break; } diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 7e5173f..8784ffd 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -2794,6 +2794,11 @@ void QWidgetPrivate::transferChildren() #ifdef QT_MAC_USE_COCOA void QWidgetPrivate::setSubWindowStacking(bool set) { + // After hitting too many unforeseen bugs trying to put Qt on top of the cocoa child + // window API, we have decided to revert this behaviour as much as we can. We + // therefore now only allow child windows to exist for children of modal dialogs. + static bool use_behaviour_qt473 = !qgetenv("QT_MAC_USE_CHILDWINDOWS").isEmpty(); + // This will set/remove a visual relationship between parent and child on screen. // The reason for doing this is to ensure that a child always stacks infront of // its parent. Unfortunatly is turns out that [NSWindow addChildWindow] has @@ -2822,7 +2827,10 @@ void QWidgetPrivate::setSubWindowStacking(bool set) if (NSWindow *pwin = [qt_mac_nativeview_for(parent) window]) { if (set) { Qt::WindowType ptype = parent->window()->windowType(); - if ([pwin isVisible] && (ptype == Qt::Window || ptype == Qt::Dialog) && ![qwin parentWindow]) { + if ([pwin isVisible] + && (ptype == Qt::Window || ptype == Qt::Dialog) + && ![qwin parentWindow] + && (use_behaviour_qt473 || parent->windowModality() == Qt::ApplicationModal)) { NSInteger level = [qwin level]; [pwin addChildWindow:qwin ordered:NSWindowAbove]; if ([qwin level] < level) @@ -2834,6 +2842,10 @@ void QWidgetPrivate::setSubWindowStacking(bool set) } } + // Only set-up child windows for q if q is modal: + if (set && !use_behaviour_qt473 && q->windowModality() != Qt::ApplicationModal) + return; + QObjectList widgets = q->children(); for (int i=0; i<widgets.size(); ++i) { QWidget *child = qobject_cast<QWidget *>(widgets.at(i)); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 5235dc4..377e3a7 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -315,6 +315,11 @@ struct QWExtra { */ ZeroFill, + /** + * Blit backing store, propagating alpha channel into the framebuffer. + */ + BlitWriteAlpha, + Default = Blit }; @@ -878,6 +883,7 @@ public: static QWidget *mouseGrabber; static QWidget *keyboardGrabber; int symbianScreenNumber; // only valid for desktop widget and top-levels + bool fixNativeOrientationCalled; void s60UpdateIsOpaque(); void reparentChildren(); void registerTouchWindow(); diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index be212fb..d55e1ad 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -278,6 +278,8 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) q->internalWinId()->SetRect(TRect(TPoint(x, y), TSize(w, h))); topData()->normalGeometry = data.crect; } + QSymbianControl *window = static_cast<QSymbianControl *>(q->internalWinId()); + window->ensureFixNativeOrientation(); } else { data.crect.setRect(x, y, w, h); @@ -805,36 +807,45 @@ void QWidgetPrivate::s60UpdateIsOpaque() { Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created) || !q->testAttribute(Qt::WA_TranslucentBackground)) + if (!q->testAttribute(Qt::WA_WState_Created)) return; + const bool writeAlpha = extraData()->nativePaintMode == QWExtra::BlitWriteAlpha; + if (!q->testAttribute(Qt::WA_TranslucentBackground) && !writeAlpha) + return; + const bool requireAlphaChannel = !isOpaque || writeAlpha; + createTLExtra(); RWindow *const window = static_cast<RWindow *>(q->effectiveWinId()->DrawableWindow()); #ifdef Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE - window->SetSurfaceTransparency(!isOpaque); - extra->topextra->nativeWindowTransparencyEnabled = !isOpaque; -#else - if (!isOpaque) { + if (QApplicationPrivate::instance()->useTranslucentEGLSurfaces) { + window->SetSurfaceTransparency(!isOpaque); + extra->topextra->nativeWindowTransparencyEnabled = !isOpaque; + return; + } +#endif + if (requireAlphaChannel) { const TDisplayMode displayMode = static_cast<TDisplayMode>(window->SetRequiredDisplayMode(EColor16MA)); if (window->SetTransparencyAlphaChannel() == KErrNone) { window->SetBackgroundColor(TRgb(255, 255, 255, 0)); extra->topextra->nativeWindowTransparencyEnabled = 1; - - if (extra->topextra->backingStore.data() && - QApplicationPrivate::graphics_system_name == QLatin1String("openvg")) { + if (extra->topextra->backingStore.data() && ( + QApplicationPrivate::graphics_system_name == QLatin1String("openvg") + || QApplicationPrivate::graphics_system_name == QLatin1String("opengl"))) { // Semi-transparent EGL surfaces aren't supported. We need to // recreate backing store to get translucent surface (raster surface). extra->topextra->backingStore.create(q); extra->topextra->backingStore.registerWidget(q); + // FixNativeOrientation() will not work without an EGL surface. + q->setAttribute(Qt::WA_SymbianNoSystemRotation, false); } } } else if (extra->topextra->nativeWindowTransparencyEnabled) { window->SetTransparentRegion(TRegionFix<1>()); extra->topextra->nativeWindowTransparencyEnabled = 0; } -#endif } void QWidgetPrivate::setWindowIcon_sys(bool forceReset) @@ -1197,17 +1208,10 @@ void QWidget::setWindowState(Qt::WindowStates newstate) } #ifdef Q_WS_S60 - bool decorationsVisible(false); - if (!parentWidget()) { // Only top level native windows have control over cba/status pane - // Hide window decoration when switching to fullscreen / minimized otherwise show decoration. - // The window decoration visibility has to be changed before doing actual window state - // change since in that order the availableGeometry will return directly the right size and - // we will avoid unnecessary redraws - decorationsVisible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized)); - const bool statusPaneVisibility = decorationsVisible; - const bool buttonGroupVisibility = (decorationsVisible || (isFullscreen && cbaRequested)); - S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility); - } + // The window decoration visibility has to be changed before doing actual window state + // change since in that order the availableGeometry will return directly the right size and + // we will avoid unnecessary redraws + bool decorationsVisible = S60->setRecursiveDecorationsVisibility(this, newstate); #endif // Q_WS_S60 // Ensure the initial size is valid, since we store it as normalGeometry below. @@ -1266,6 +1270,12 @@ void QWidget::setWindowState(Qt::WindowStates newstate) if (newstate & Qt::WindowActive) activateWindow(); + if (isWindow()) { + // Now that the new state is set, fix the display memory layout, if needed. + QSymbianControl *window = static_cast<QSymbianControl *>(effectiveWinId()); + window->ensureFixNativeOrientation(); + } + QWindowStateChangeEvent e(oldstate); QApplication::sendEvent(this, &e); } @@ -1412,7 +1422,8 @@ void QWidget::activateWindow() if (tlw->isVisible()) { window()->createWinId(); QSymbianControl *id = static_cast<QSymbianControl *>(tlw->internalWinId()); - id->setFocusSafely(true); + if (!id->IsFocused()) + id->setFocusSafely(true); } } |