diff options
author | Laszlo Agocs <laszlo.p.agocs@nokia.com> | 2011-04-12 10:35:41 (GMT) |
---|---|---|
committer | Laszlo Agocs <laszlo.p.agocs@nokia.com> | 2011-04-12 10:35:41 (GMT) |
commit | 565e8679374e71df9f72074dd3c71c929aeeafc8 (patch) | |
tree | c135fc6befac2a771991fd71c70409d63af25a56 /src | |
parent | 8b9c94c95ef5dd9620dc35c4ab20cd109369636f (diff) | |
download | Qt-565e8679374e71df9f72074dd3c71c929aeeafc8.zip Qt-565e8679374e71df9f72074dd3c71c929aeeafc8.tar.gz Qt-565e8679374e71df9f72074dd3c71c929aeeafc8.tar.bz2 |
Use FixNativeOrientation on Symbian when the application wants it.
Applications can request the usage of RWindow::FixNativeOrientation()
by setting the new Qt::WA_SymbianNoSystemRotation attribute for their
fullscreen top-level widget (which in practice will either be a
graphics or declarative view). This will fix the underlying EGL
window surface and the QWidget dimensions to the dimension of the
native orientation of the device (typically portrait). The default
auto-rotation can be left enabled, however it will be up to the
application to rotate the drawing. Global notifications, VKB, etc.
will still appear in the proper orientation. Another benefit is
improved performance in the non-native orientation.
Task-number: QTBUG-17742
Reviewed-by: Jason Barron
Reviewed-by: Jani Hautakangas
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/global/qnamespace.h | 2 | ||||
-rw-r--r-- | src/corelib/global/qnamespace.qdoc | 1 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 159 | ||||
-rw-r--r-- | src/gui/kernel/qt_s60_p.h | 15 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_s60.cpp | 2 |
5 files changed, 132 insertions, 47 deletions
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 4d70744..15cc809 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -526,6 +526,8 @@ public: WA_X11DoNotAcceptFocus = 132, + WA_SymbianNoSystemRotation = 133, + // Add new attributes before this line WA_AttributeCount }; diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 22ad83b..f03fb25 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -1244,6 +1244,7 @@ \omitvalue WA_SetWindowModality \omitvalue WA_WState_WindowOpacitySet \omitvalue WA_WState_AcceptedTouchBeginEvent + \omitvalue WA_SymbianNoSystemRotation */ /*! \typedef Qt::HANDLE diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index f80b657..d37845d 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -546,11 +546,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; @@ -565,7 +606,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 @@ -666,7 +707,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; @@ -1132,6 +1173,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()) { @@ -1142,7 +1186,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; } @@ -1155,7 +1199,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)); } @@ -1210,7 +1254,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, @@ -1223,14 +1267,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) { @@ -1243,26 +1318,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; @@ -1513,29 +1570,49 @@ bool QSymbianControl::isControlActive() void QSymbianControl::ensureFixNativeOrientation() { #if defined(Q_SYMBIAN_SUPPORTS_FIXNATIVEORIENTATION) - // Call FixNativeOrientation() for fullscreen QDeclarativeViews that - // have a locked orientation matching the native orientation of the device. - // This avoids unnecessary window rotation on wserv level. - if (!qwidget->isWindow() || qwidget->windowType() == Qt::Desktop - || !qwidget->inherits("QDeclarativeView") - || S60->screenNumberForWidget(qwidget) > 0) + if (!qwidget->isWindow() || qwidget->windowType() == Qt::Desktop) + return; + if (S60->screenNumberForWidget(qwidget) > 0) return; - const bool isFullScreen = qwidget->windowState().testFlag(Qt::WindowFullScreen); const bool isFixed = qwidget->d_func()->fixNativeOrientationCalled; - const bool matchesNative = qwidget->testAttribute( - S60->nativeOrientationIsPortrait ? Qt::WA_LockPortraitOrientation - : Qt::WA_LockLandscapeOrientation); - if (isFullScreen && matchesNative) { - if (!isFixed) { - Window().FixNativeOrientation(); - qwidget->d_func()->fixNativeOrientationCalled = true; + 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 } diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index c48bf63..e24405c 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -191,7 +191,8 @@ public: int screenWidthInTwipsForScreen[qt_symbian_max_screens]; int screenHeightInTwipsForScreen[qt_symbian_max_screens]; - bool nativeOrientationIsPortrait; + int nativeScreenWidthInPixels; + int nativeScreenHeightInPixels; }; Q_AUTOTEST_EXPORT QS60Data* qGlobalS60Data(); @@ -237,6 +238,8 @@ 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); } @@ -256,6 +259,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); @@ -363,18 +369,15 @@ inline void QS60Data::updateScreenSize() // Look for a screen mode with rotation 0 // in order to decide what the native orientation is. - int nativeScreenWidthInPixels = 0; - int nativeScreenHeightInPixels = 0; for (mode = 0; mode < screenModeCount; ++mode) { TPixelsAndRotation sizeAndRotation; dev->GetScreenModeSizeAndRotation(mode, sizeAndRotation); if (sizeAndRotation.iRotation == CFbsBitGc::EGraphicsOrientationNormal) { - nativeScreenWidthInPixels = sizeAndRotation.iPixelSize.iWidth; - nativeScreenHeightInPixels = sizeAndRotation.iPixelSize.iHeight; + S60->nativeScreenWidthInPixels = sizeAndRotation.iPixelSize.iWidth; + S60->nativeScreenHeightInPixels = sizeAndRotation.iPixelSize.iHeight; break; } } - S60->nativeOrientationIsPortrait = nativeScreenWidthInPixels <= nativeScreenHeightInPixels; } inline RWsSession& QS60Data::wsSession() diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 10bb98b..d55e1ad 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -838,6 +838,8 @@ void QWidgetPrivate::s60UpdateIsOpaque() // 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) { |