diff --git a/examples/opengl/paintedwindow/main.cpp b/examples/opengl/paintedwindow/main.cpp index a235646aaccd4454844621fd89d72f6eca5446e2..6ca3c245ca6b9bccb93b5726248363b2959b20b2 100644 --- a/examples/opengl/paintedwindow/main.cpp +++ b/examples/opengl/paintedwindow/main.cpp @@ -40,7 +40,6 @@ #include <QGuiApplication> #include <QRect> -#include <QScreen> #include "paintedwindow.h" @@ -48,15 +47,7 @@ int main(int argc, char **argv) { QGuiApplication app(argc, argv); - QScreen *screen = QGuiApplication::primaryScreen(); - - QRect screenGeometry = screen->availableGeometry(); - - QPoint center = screenGeometry.center(); - QRect windowRect(0, 0, 480, 640); - PaintedWindow window; - window.setGeometry(QRect(center - windowRect.center(), windowRect.size())); window.show(); app.exec(); diff --git a/examples/opengl/paintedwindow/paintedwindow.cpp b/examples/opengl/paintedwindow/paintedwindow.cpp index 51b6ec0ee0075ee445bca5262b94b9eb0149b89a..bdb4eaf66cd657ccb12bc8908d3da3d206ea2af6 100644 --- a/examples/opengl/paintedwindow/paintedwindow.cpp +++ b/examples/opengl/paintedwindow/paintedwindow.cpp @@ -70,13 +70,22 @@ PaintedWindow::PaintedWindow() m_animation->setEndValue(qreal(1)); m_animation->setDuration(500); - setOrientation(QGuiApplication::primaryScreen()->primaryOrientation()); + requestWindowOrientation(Qt::PortraitOrientation); + + QRect screenGeometry = screen()->availableGeometry(); + + QPoint center = screenGeometry.center(); + QRect windowRect = screen()->isLandscape(windowOrientation()) ? QRect(0, 0, 640, 480) : QRect(0, 0, 480, 640); + setGeometry(QRect(center - windowRect.center(), windowRect.size())); + m_rotation = 0; - m_targetOrientation = orientation(); - m_nextTargetOrientation = Qt::UnknownOrientation; + reportContentOrientationChange(screen()->orientation()); - connect(screen(), SIGNAL(currentOrientationChanged(Qt::ScreenOrientation)), this, SLOT(orientationChanged(Qt::ScreenOrientation))); + m_targetOrientation = contentOrientation(); + m_nextTargetOrientation = Qt::PrimaryOrientation; + + connect(screen(), SIGNAL(orientationChanged(Qt::ScreenOrientation)), this, SLOT(orientationChanged(Qt::ScreenOrientation))); connect(m_animation, SIGNAL(finished()), this, SLOT(rotationDone())); connect(this, SIGNAL(rotationChanged(qreal)), this, SLOT(paint())); } @@ -93,7 +102,7 @@ void PaintedWindow::exposeEvent(QExposeEvent *) void PaintedWindow::mousePressEvent(QMouseEvent *) { - Qt::ScreenOrientation o = orientation(); + Qt::ScreenOrientation o = contentOrientation(); switch (o) { case Qt::LandscapeOrientation: orientationChanged(Qt::PortraitOrientation); @@ -116,7 +125,7 @@ void PaintedWindow::mousePressEvent(QMouseEvent *) void PaintedWindow::orientationChanged(Qt::ScreenOrientation newOrientation) { - if (orientation() == newOrientation) + if (contentOrientation() == newOrientation) return; if (m_animation->state() == QAbstractAnimation::Running) { @@ -124,8 +133,6 @@ void PaintedWindow::orientationChanged(Qt::ScreenOrientation newOrientation) return; } - Qt::ScreenOrientation screenOrientation = screen()->primaryOrientation(); - QRect rect(0, 0, width(), height()); m_prevImage = QImage(width(), height(), QImage::Format_ARGB32_Premultiplied); @@ -135,16 +142,16 @@ void PaintedWindow::orientationChanged(Qt::ScreenOrientation newOrientation) QPainter p; p.begin(&m_prevImage); - p.setTransform(QScreen::transformBetween(orientation(), screenOrientation, rect)); - paint(&p, QScreen::mapBetween(orientation(), screenOrientation, rect)); + p.setTransform(screen()->transformBetween(contentOrientation(), windowOrientation(), rect)); + paint(&p, screen()->mapBetween(contentOrientation(), windowOrientation(), rect)); p.end(); p.begin(&m_nextImage); - p.setTransform(QScreen::transformBetween(newOrientation, screenOrientation, rect)); - paint(&p, QScreen::mapBetween(newOrientation, screenOrientation, rect)); + p.setTransform(screen()->transformBetween(newOrientation, windowOrientation(), rect)); + paint(&p, screen()->mapBetween(newOrientation, windowOrientation(), rect)); p.end(); - m_deltaRotation = QScreen::angleBetween(newOrientation, orientation()); + m_deltaRotation = screen()->angleBetween(newOrientation, contentOrientation()); if (m_deltaRotation > 180) m_deltaRotation = 180 - m_deltaRotation; @@ -154,11 +161,11 @@ void PaintedWindow::orientationChanged(Qt::ScreenOrientation newOrientation) void PaintedWindow::rotationDone() { - setOrientation(m_targetOrientation); - if (m_nextTargetOrientation != Qt::UnknownOrientation) { + reportContentOrientationChange(m_targetOrientation); + if (m_nextTargetOrientation != Qt::PrimaryOrientation) { Q_ASSERT(m_animation->state() != QAbstractAnimation::Running); orientationChanged(m_nextTargetOrientation); - m_nextTargetOrientation = Qt::UnknownOrientation; + m_nextTargetOrientation = Qt::PrimaryOrientation; } } @@ -174,9 +181,6 @@ void PaintedWindow::paint() { m_context->makeCurrent(this); - Qt::ScreenOrientation screenOrientation = screen()->primaryOrientation(); - Qt::ScreenOrientation appOrientation = orientation(); - QRect rect(0, 0, width(), height()); QOpenGLPaintDevice device(size()); @@ -189,7 +193,7 @@ void PaintedWindow::paint() painter.setCompositionMode(QPainter::CompositionMode_SourceOver); painter.fillPath(path, Qt::blue); - if (orientation() != m_targetOrientation) { + if (contentOrientation() != m_targetOrientation) { painter.setRenderHint(QPainter::SmoothPixmapTransform); painter.save(); painter.translate(width() / 2, height() / 2); @@ -203,9 +207,9 @@ void PaintedWindow::paint() painter.setOpacity(m_rotation); painter.drawImage(0, 0, m_nextImage); } else { - QRect mapped = QScreen::mapBetween(appOrientation, screenOrientation, rect); + QRect mapped = screen()->mapBetween(contentOrientation(), windowOrientation(), rect); - painter.setTransform(QScreen::transformBetween(appOrientation, screenOrientation, rect)); + painter.setTransform(screen()->transformBetween(contentOrientation(), windowOrientation(), rect)); paint(&painter, mapped); painter.end(); } diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 521e426258c6f8af6e0d1399e12acd1a1ab90ca6..3107d50bd9fd48d7017f5e57ddd91197eb444261 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -317,7 +317,7 @@ public: Q_DECLARE_FLAGS(WindowStates, WindowState) enum ScreenOrientation { - UnknownOrientation = 0x00000000, + PrimaryOrientation = 0x00000000, PortraitOrientation = 0x00000001, LandscapeOrientation = 0x00000002, InvertedPortraitOrientation = 0x00000004, diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 0e98aaa5523e23122c0fe278cac76088aa809aff..37be933393afe1279730451fc19f219946d878a8 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -1821,7 +1821,8 @@ This enum type specifies the various orientations a screen might have. - \value UnknownOrientation The orientation is unknown or the platform doesn't support orientations. + \value PrimaryOrientation The display's primary orientation. The QWindow and QScreen APIs never return this value, + instead it will be mapped to the corresponding QScreen's QScreen::primaryOrientation(). \value LandscapeOrientation Landscape orientation, display width is greater than display height. \value PortraitOrientation Portrait orientation, display height is greater than display width, rotated 90 degree clockwise relative to landscape. diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 6a8f8582be048e6ec2af99e38f98859ed4a55d1f..b3adcfcbaf8ffc243c5f7e4d6cf8c7eabbfec037 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1078,11 +1078,16 @@ void QGuiApplicationPrivate::reportScreenOrientationChange(QWindowSystemInterfac return; QScreen *s = e->screen.data(); - s->d_func()->currentOrientation = e->orientation; + s->d_func()->orientation = e->orientation; - emit s->currentOrientationChanged(s->currentOrientation()); + reportScreenOrientationChange(s); +} + +void QGuiApplicationPrivate::reportScreenOrientationChange(QScreen *s) +{ + emit s->orientationChanged(s->orientation()); - QScreenOrientationChangeEvent event(s, s->currentOrientation()); + QScreenOrientationChangeEvent event(s, s->orientation()); QCoreApplication::sendEvent(QCoreApplication::instance(), &event); } @@ -1098,6 +1103,10 @@ void QGuiApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate: QScreen *s = e->screen.data(); s->d_func()->geometry = e->geometry; + Qt::ScreenOrientation primaryOrientation = s->primaryOrientation(); + Qt::ScreenOrientation orientation = s->orientation(); + s->d_func()->updatePrimaryOrientation(); + emit s->sizeChanged(s->size()); emit s->geometryChanged(s->geometry()); emit s->physicalDotsPerInchXChanged(s->physicalDotsPerInchX()); @@ -1105,6 +1114,12 @@ void QGuiApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate: emit s->physicalDotsPerInchChanged(s->physicalDotsPerInch()); emit s->availableSizeChanged(s->availableSize()); emit s->availableGeometryChanged(s->availableGeometry()); + + if (s->primaryOrientation() != primaryOrientation) + emit s->primaryOrientationChanged(s->primaryOrientation()); + + if (s->orientation() != orientation) + reportScreenOrientationChange(s); } void QGuiApplicationPrivate::reportAvailableGeometryChange( diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 09db13e28eeb5ea85b765eb8961426bbfb2a5dc8..7881d8a9555e3ddbcfd3a94616714bcfd8ee5626 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -122,6 +122,7 @@ public: static void processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e); + static void reportScreenOrientationChange(QScreen *screen); static void reportScreenOrientationChange(QWindowSystemInterfacePrivate::ScreenOrientationEvent *e); static void reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e); static void reportAvailableGeometryChange(QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e); diff --git a/src/gui/kernel/qplatformscreen_qpa.cpp b/src/gui/kernel/qplatformscreen_qpa.cpp index 7006b77a36740aa7ff822b564502895424aa2c43..37a3aeddc843e8c347446fbeb52cfcbe95ee2071 100644 --- a/src/gui/kernel/qplatformscreen_qpa.cpp +++ b/src/gui/kernel/qplatformscreen_qpa.cpp @@ -159,37 +159,16 @@ QDpi QPlatformScreen::logicalDpi() const 25.4 * s.height() / ps.height()); } -/*! - Reimplement this function in subclass to return the primary orientation - of the screen, i.e. the orientation the display controller or equivalent - expects. - - The default implementation returns Qt::PortraitOrientation if the - geometry's height is greater or Qt::LandscapeOrientation if the geometry's - width is greater. -*/ -Qt::ScreenOrientation QPlatformScreen::primaryOrientation() const -{ - return geometry().height() > geometry().width() ? Qt::PortraitOrientation : - Qt::LandscapeOrientation; -} - /*! Reimplement this function in subclass to return the current orientation of the screen, for example based on accelerometer data to determine - the physical screen orientation. - - The current orientation is only a hint to the application saying - what the preferred application orientation should be, the application - is free to limit itself to a certain set of supported orientations. - - The default implementation returns the same as primaryOrientation(). + the device orientation. - \sa primaryOrientation() + The default implementation returns Qt::PrimaryOrientation. */ -Qt::ScreenOrientation QPlatformScreen::currentOrientation() const +Qt::ScreenOrientation QPlatformScreen::orientation() const { - return primaryOrientation(); + return Qt::PrimaryOrientation; } QPlatformScreen * QPlatformScreen::platformScreenForWindow(const QWindow *window) diff --git a/src/gui/kernel/qplatformscreen_qpa.h b/src/gui/kernel/qplatformscreen_qpa.h index 09a243aa83f8a3cd334492d04bbb20866be12171..04cc2ccc399d97025496dd6146718f4115528de3 100644 --- a/src/gui/kernel/qplatformscreen_qpa.h +++ b/src/gui/kernel/qplatformscreen_qpa.h @@ -99,8 +99,7 @@ public: virtual QSizeF physicalSize() const; virtual QDpi logicalDpi() const; - virtual Qt::ScreenOrientation currentOrientation() const; - virtual Qt::ScreenOrientation primaryOrientation() const; + virtual Qt::ScreenOrientation orientation() const; virtual QWindow *topLevelAt(const QPoint &point) const; virtual QList<QPlatformScreen *> virtualSiblings() const; diff --git a/src/gui/kernel/qplatformwindow_qpa.cpp b/src/gui/kernel/qplatformwindow_qpa.cpp index 463267869c3665869c1e124ba0dc311dcb963938..b9506e7999db7aace61a8a9eac5af44bb589d5c6 100644 --- a/src/gui/kernel/qplatformwindow_qpa.cpp +++ b/src/gui/kernel/qplatformwindow_qpa.cpp @@ -239,19 +239,44 @@ void QPlatformWindow::requestActivateWindow() } /*! - Set the orientation of the platform window's contents. + Handle changes to the orientation of the platform window's contents. This is a hint to the window manager in case it needs to display additional content like popups, dialogs, status bars, or similar in relation to the window. - \sa QWindow::setOrientation() + \sa QWindow::reportContentOrientationChange() */ -void QPlatformWindow::setOrientation(Qt::ScreenOrientation orientation) +void QPlatformWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation) { Q_UNUSED(orientation); } +/*! + Request a different orientation of the platform window. + + This tells the window manager how the window wants to be rotated in order + to be displayed, and how input events should be translated. + + As an example, a portrait compositor might rotate the window by 90 degrees, + if the window is in landscape. It will also rotate input coordinates from + portrait to landscape such that top right in portrait gets mapped to top + left in landscape. + + If the implementation doesn't support the requested orientation it should + signal this by returning an actual supported orientation. + + If the implementation doesn't support rotating the window at all it should + return Qt::PrimaryOrientation, this is also the default value. + + \sa QWindow::requestWindowOrientation() +*/ +Qt::ScreenOrientation QPlatformWindow::requestWindowOrientation(Qt::ScreenOrientation orientation) +{ + Q_UNUSED(orientation); + return Qt::PrimaryOrientation; +} + bool QPlatformWindow::setKeyboardGrabEnabled(bool grab) { Q_UNUSED(grab); diff --git a/src/gui/kernel/qplatformwindow_qpa.h b/src/gui/kernel/qplatformwindow_qpa.h index 509cf30fa8b8cc7ef92526bc24aae2ef90805632..de5c955eba2acb95109273e13571afc3cc7814e4 100644 --- a/src/gui/kernel/qplatformwindow_qpa.h +++ b/src/gui/kernel/qplatformwindow_qpa.h @@ -95,7 +95,8 @@ public: virtual void setOpacity(qreal level); virtual void requestActivateWindow(); - virtual void setOrientation(Qt::ScreenOrientation orientation); + virtual void handleContentOrientationChange(Qt::ScreenOrientation orientation); + virtual Qt::ScreenOrientation requestWindowOrientation(Qt::ScreenOrientation orientation); virtual bool setKeyboardGrabEnabled(bool grab); virtual bool setMouseGrabEnabled(bool grab); diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp index 0a7d22c6c80bca54aff5aa81cc3c6be48c836fa8..43c2dcc50def1413ff9878a265019c1015a0b008 100644 --- a/src/gui/kernel/qscreen.cpp +++ b/src/gui/kernel/qscreen.cpp @@ -343,35 +343,36 @@ QRect QScreen::availableVirtualGeometry() const } /*! - \property QScreen::primaryOrientation - \brief the primary screen orientation + \property QScreen::orientation + \brief the screen orientation + + The screen orientation represents the physical orientation + of the display. For example, the screen orientation of a mobile device + will change based on the device is being held, and a desktop display + might be rotated so that it's in portrait mode. - The primary screen orientation is the orientation that corresponds - to an un-rotated screen buffer. When the current orientation is equal - to the primary orientation no rotation needs to be done by the - application. + \sa primaryOrientation(), orientationChanged() */ -Qt::ScreenOrientation QScreen::primaryOrientation() const +Qt::ScreenOrientation QScreen::orientation() const { Q_D(const QScreen); - return d->platformScreen->primaryOrientation(); + return d->orientation == Qt::PrimaryOrientation ? primaryOrientation() : d->orientation; } /*! \property QScreen::primaryOrientation - \brief the current screen orientation + \brief the primary screen orientation - The current orientation is a hint to the application saying - what the preferred application orientation should be, based on the - current orientation of the physical display and / or other factors. + The primary screen orientation is Qt::LandscapeOrientation + if the screen geometry's width is greater than or equal to its + height, or Qt::PortraitOrientation otherwise. - \sa primaryOrientation() - \sa currentOrientationChanged() + \sa primaryOrientationChanged() */ -Qt::ScreenOrientation QScreen::currentOrientation() const +Qt::ScreenOrientation QScreen::primaryOrientation() const { Q_D(const QScreen); - return d->currentOrientation; + return d->primaryOrientation; } // i must be power of two @@ -393,10 +394,18 @@ static int log2(uint i) rotation \a a to rotation \a b. The result will be 0, 90, 180, or 270. + + Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). */ int QScreen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b) { - if (a == Qt::UnknownOrientation || b == Qt::UnknownOrientation || a == b) + if (a == Qt::PrimaryOrientation) + a = primaryOrientation(); + + if (b == Qt::PrimaryOrientation) + b = primaryOrientation(); + + if (a == b) return 0; int ia = log2(uint(a)); @@ -420,10 +429,18 @@ int QScreen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b) the resulting transform will be such that the point QPoint(0, 0) is mapped to QPoint(0, w), and QPoint(h, w) is mapped to QPoint(0, h). Thus, the landscape coordinate system QRect(0, 0, h, w) is mapped (with a 90 degree rotation) into the portrait coordinate system QRect(0, 0, w, h). + + Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). */ QTransform QScreen::transformBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &target) { - if (a == Qt::UnknownOrientation || b == Qt::UnknownOrientation || a == b) + if (a == Qt::PrimaryOrientation) + a = primaryOrientation(); + + if (b == Qt::PrimaryOrientation) + b = primaryOrientation(); + + if (a == b) return QTransform(); int angle = angleBetween(a, b); @@ -453,10 +470,18 @@ QTransform QScreen::transformBetween(Qt::ScreenOrientation a, Qt::ScreenOrientat This will flip the x and y dimensions of the rectangle if orientation \a is Qt::PortraitOrientation or Qt::InvertedPortraitOrientation and orientation \b is Qt::LandscapeOrientation or Qt::InvertedLandscapeOrientation, or vice versa. + + Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). */ QRect QScreen::mapBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &rect) { - if (a == Qt::UnknownOrientation || b == Qt::UnknownOrientation || a == b) + if (a == Qt::PrimaryOrientation) + a = primaryOrientation(); + + if (b == Qt::PrimaryOrientation) + b = primaryOrientation(); + + if (a == b) return rect; if ((a == Qt::PortraitOrientation || a == Qt::InvertedPortraitOrientation) @@ -469,14 +494,50 @@ QRect QScreen::mapBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, cons } /*! - \fn QScreen::currentOrientationChanged(Qt::ScreenOrientation orientation) + Convenience function to check if a screen orientation is either portrait + or inverted portrait. - This signal is emitted when the current orientation of the screen - changes. The current orientation is a hint to the application saying - what the preferred application orientation should be, based on the - current orientation of the physical display and / or other factors. + Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). +*/ +bool QScreen::isPortrait(Qt::ScreenOrientation o) +{ + return o == Qt::PortraitOrientation || o == Qt::InvertedPortraitOrientation + || (o == Qt::PrimaryOrientation && primaryOrientation() == Qt::PortraitOrientation); +} - \sa currentOrientation() +/*! + Convenience function to check if a screen orientation is either landscape + or inverted landscape. + + Qt::PrimaryOrientation is interpreted as the screen's primaryOrientation(). +*/ +bool QScreen::isLandscape(Qt::ScreenOrientation o) +{ + return o == Qt::LandscapeOrientation || o == Qt::InvertedLandscapeOrientation + || (o == Qt::PrimaryOrientation && primaryOrientation() == Qt::LandscapeOrientation); +} + +/*! + \fn QScreen::orientationChanged(Qt::ScreenOrientation orientation) + + This signal is emitted when the orientation of the screen + changes. + + \sa orientation() */ +/*! + \fn QScreen::primaryOrientationChanged(Qt::ScreenOrientation orientation) + + This signal is emitted when the primary orientation of the screen + changes. + + \sa primaryOrientation() +*/ + +void QScreenPrivate::updatePrimaryOrientation() +{ + primaryOrientation = geometry.width() >= geometry.height() ? Qt::LandscapeOrientation : Qt::PortraitOrientation; +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qscreen.h b/src/gui/kernel/qscreen.h index c45590c1b4f81247627748deb0113b92fb47c614..aa3d750b416d9670ae04923614d33c1368dbb284 100644 --- a/src/gui/kernel/qscreen.h +++ b/src/gui/kernel/qscreen.h @@ -81,8 +81,8 @@ class Q_GUI_EXPORT QScreen : public QObject Q_PROPERTY(qreal logicalDotsPerInch READ logicalDotsPerInch NOTIFY logicalDotsPerInchChanged) Q_PROPERTY(QSize availableSize READ availableSize NOTIFY availableSizeChanged) Q_PROPERTY(QRect availableGeometry READ availableGeometry NOTIFY availableGeometryChanged) - Q_PROPERTY(Qt::ScreenOrientation primaryOrientation READ primaryOrientation CONSTANT) - Q_PROPERTY(Qt::ScreenOrientation currentOrientation READ currentOrientation NOTIFY currentOrientationChanged) + Q_PROPERTY(Qt::ScreenOrientation primaryOrientation READ orientation NOTIFY primaryOrientationChanged) + Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation NOTIFY orientationChanged) public: QPlatformScreen *handle() const; @@ -116,11 +116,14 @@ public: QRect availableVirtualGeometry() const; Qt::ScreenOrientation primaryOrientation() const; - Qt::ScreenOrientation currentOrientation() const; + Qt::ScreenOrientation orientation() const; - static int angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b); - static QTransform transformBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &target); - static QRect mapBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &rect); + int angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b); + QTransform transformBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &target); + QRect mapBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &rect); + + bool isPortrait(Qt::ScreenOrientation orientation); + bool isLandscape(Qt::ScreenOrientation orientation); Q_SIGNALS: void sizeChanged(const QSize &size); @@ -133,7 +136,8 @@ Q_SIGNALS: void logicalDotsPerInchChanged(qreal dpi); void availableSizeChanged(const QSize &size); void availableGeometryChanged(const QRect &rect); - void currentOrientationChanged(Qt::ScreenOrientation orientation); + void primaryOrientationChanged(Qt::ScreenOrientation orientation); + void orientationChanged(Qt::ScreenOrientation orientation); private: QScreen(QPlatformScreen *screen); diff --git a/src/gui/kernel/qscreen_p.h b/src/gui/kernel/qscreen_p.h index 545534df2919a00d22285cd2a3b408271a54059d..2fdf12dd90808daa5e52098088079427bc41627b 100644 --- a/src/gui/kernel/qscreen_p.h +++ b/src/gui/kernel/qscreen_p.h @@ -59,13 +59,18 @@ public: QScreenPrivate(QPlatformScreen *screen) : platformScreen(screen) { - currentOrientation = screen->currentOrientation(); + orientation = screen->orientation(); geometry = screen->geometry(); availableGeometry = screen->availableGeometry(); logicalDpi = screen->logicalDpi(); + + updatePrimaryOrientation(); } - Qt::ScreenOrientation currentOrientation; + void updatePrimaryOrientation(); + + Qt::ScreenOrientation orientation; + Qt::ScreenOrientation primaryOrientation; QRect geometry; QRect availableGeometry; QDpi logicalDpi; diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 2893273ce075c2ea6e5138e74ad15d652c8090a5..65ac5f1539f974a32425689a604110c83efede8e 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -72,8 +72,24 @@ QT_BEGIN_NAMESPACE to support double and triple buffering. To release a windows memory resources, the destroy() function. - */ - + \section1 Window and content orientation + + QWindow has reportContentOrientationChange() and + requestWindowOrientation() that can be used to specify the + layout of the window contents in relation to the screen. The + window orientation determines the actual buffer layout of the + window, and the windowing system uses this value to rotate the + window before it ends up on the display, and to ensure that input + coordinates are in the correct coordinate space relative to the + application. + + On the other hand, the content orientation is simply a hint to the + windowing system about which orientation the window contents are in. + It's useful when you wish to keep the same buffer layout, but rotate + the contents instead, especially when doing rotation animations + between different orientations. The windowing system might use this + value to determine the layout of system popups or dialogs. +*/ QWindow::QWindow(QScreen *targetScreen) : QObject(*new QWindowPrivate(), 0) , QSurface(QSurface::Window) @@ -375,42 +391,82 @@ bool QWindow::isActive() const } /*! - Returns the window's currently set orientation. + Reports that the orientation of the window's contents have changed. + + This is a hint to the window manager in case it needs to display + additional content like popups, dialogs, status bars, or similar + in relation to the window. + + The recommended orientation is QScreen::orientation() but + an application doesn't have to support all possible orientations, + and thus can opt to ignore the current screen orientation. + + The difference between the window and the content orientation + determines how much to rotate the content by. QScreen::angleBetween(), + QScreen::transformBetween(), and QScreen::mapBetween() can be used + to compute the necessary transform. + + \sa requestWindowOrientation(), QScreen::orientation() +*/ +void QWindow::reportContentOrientationChange(Qt::ScreenOrientation orientation) +{ + Q_D(QWindow); + if (!d->platformWindow) + create(); + Q_ASSERT(d->platformWindow); + d->contentOrientation = orientation; + d->platformWindow->handleContentOrientationChange(orientation); +} - The default value is Qt::UnknownOrientation. +/*! + Returns the actual content orientation. - \sa setOrientation(), QScreen::currentOrientation() + This is the last value set with reportContentOrientationChange(), + except Qt::PrimaryOrientation gets converted to the screen's + primary orientation. */ -Qt::ScreenOrientation QWindow::orientation() const +Qt::ScreenOrientation QWindow::contentOrientation() const { Q_D(const QWindow); - return d->orientation; + return d->contentOrientation == Qt::PrimaryOrientation ? screen()->primaryOrientation() : d->contentOrientation; } /*! - Set the orientation of the window's contents. + Requests the given window orientation. - This is a hint to the window manager in case it needs to display - additional content like popups, dialogs, status bars, or similar - in relation to the window. + The window orientation specifies how the window should be rotated + by the window manager in order to be displayed. Input events will + be correctly mapped to the given orientation. - The recommended orientation is QScreen::currentOrientation() but - an application doesn't have to support all possible orientations, - and thus can opt to ignore the current screen orientation. + The return value is false if the system doesn't support the given + orientation (for example when requesting a portrait orientation + on a device that only handles landscape buffers, typically a desktop + system). + + If the return value is false, call windowOrientation() to get the actual + supported orientation. - \sa QScreen::currentOrientation() + \sa windowOrientation(), reportContentOrientationChange(), QScreen::orientation() */ -void QWindow::setOrientation(Qt::ScreenOrientation orientation) +bool QWindow::requestWindowOrientation(Qt::ScreenOrientation orientation) { Q_D(QWindow); - if (orientation == d->orientation) - return; + if (!d->platformWindow) + create(); + Q_ASSERT(d->platformWindow); + d->windowOrientation = d->platformWindow->requestWindowOrientation(orientation); + return d->windowOrientation == orientation; +} - d->orientation = orientation; - if (d->platformWindow) { - d->platformWindow->setOrientation(orientation); - } - emit orientationChanged(orientation); +/*! + Returns the actual window orientation. + + \sa requestWindowOrientation() +*/ +Qt::ScreenOrientation QWindow::windowOrientation() const +{ + Q_D(const QWindow); + return d->windowOrientation == Qt::PrimaryOrientation ? screen()->primaryOrientation() : d->windowOrientation; } Qt::WindowState QWindow::windowState() const diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h index 6f3c64fe15d734e7be672bcf7d95d9f3489987f4..088192d7149b6b7fad9d1717bb71b9889284affa 100644 --- a/src/gui/kernel/qwindow.h +++ b/src/gui/kernel/qwindow.h @@ -91,7 +91,6 @@ class Q_GUI_EXPORT QWindow : public QObject, public QSurface Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged) Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged) Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibleChanged) - Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged) public: enum SurfaceType { RasterSurface, OpenGLSurface }; @@ -133,8 +132,11 @@ public: bool isActive() const; - Qt::ScreenOrientation orientation() const; - void setOrientation(Qt::ScreenOrientation orientation); + void reportContentOrientationChange(Qt::ScreenOrientation orientation); + Qt::ScreenOrientation contentOrientation() const; + + bool requestWindowOrientation(Qt::ScreenOrientation orientation); + Qt::ScreenOrientation windowOrientation() const; Qt::WindowState windowState() const; void setWindowState(Qt::WindowState state); @@ -252,17 +254,13 @@ Q_SIGNALS: void screenChanged(QScreen *screen); void xChanged(int arg); - void yChanged(int arg); void widthChanged(int arg); - void heightChanged(int arg); void visibleChanged(bool arg); - void orientationChanged(Qt::ScreenOrientation arg); - private Q_SLOTS: void screenDestroyed(QObject *screen); diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index 2bb9173d9491159f47730e0247416caeec07643d..2e28205f862069dbafcd0d1e9c0c70f8b12bb392 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -76,7 +76,8 @@ public: , windowState(Qt::WindowNoState) , resizeEventPending(true) , positionPolicy(WindowFrameExclusive) - , orientation(Qt::UnknownOrientation) + , contentOrientation(Qt::PrimaryOrientation) + , windowOrientation(Qt::PrimaryOrientation) , maximumSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX) , modality(Qt::NonModal) , transientParent(0) @@ -111,7 +112,8 @@ public: Qt::WindowState windowState; bool resizeEventPending; PositionPolicy positionPolicy; - Qt::ScreenOrientation orientation; + Qt::ScreenOrientation contentOrientation; + Qt::ScreenOrientation windowOrientation; QSize minimumSize; QSize maximumSize; diff --git a/src/plugins/platforminputcontexts/meego/qmeegoplatforminputcontext.cpp b/src/plugins/platforminputcontexts/meego/qmeegoplatforminputcontext.cpp index a2324152fc9105bf6bb397f6ec580af05d74fcd6..dc0a4f286d3f51f4607921883e9215e34f9f9da5 100644 --- a/src/plugins/platforminputcontexts/meego/qmeegoplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/meego/qmeegoplatforminputcontext.cpp @@ -467,7 +467,7 @@ void QMeeGoPlatformInputContext::inputItemChanged() // ### react to orientation changes, too if (window) - d->server->appOrientationChanged(orientationAngle(window->screen()->currentOrientation())); + d->server->appOrientationChanged(orientationAngle(window->screen()->orientation())); } } d->sendStateUpdate(/*focusChanged*/true); diff --git a/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp b/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp index d4d6ff1401a1f595d0e9c06f273dfc3861b43cee..5f2be632634bd4d37306f6dab3901185300f4766 100644 --- a/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp +++ b/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp @@ -90,6 +90,11 @@ void tst_QScreen::angleBetween_data() << uint(Qt::InvertedLandscapeOrientation) << uint(Qt::LandscapeOrientation) << 180; + + QTest::newRow("Landscape Primary") + << uint(Qt::LandscapeOrientation) + << uint(Qt::PrimaryOrientation) + << QGuiApplication::primaryScreen()->angleBetween(Qt::LandscapeOrientation, QGuiApplication::primaryScreen()->primaryOrientation()); } void tst_QScreen::angleBetween() @@ -101,8 +106,8 @@ void tst_QScreen::angleBetween() Qt::ScreenOrientation a = Qt::ScreenOrientation(oa); Qt::ScreenOrientation b = Qt::ScreenOrientation(ob); - QCOMPARE(QScreen::angleBetween(a, b), expected); - QCOMPARE(QScreen::angleBetween(b, a), (360 - expected) % 360); + QCOMPARE(QGuiApplication::primaryScreen()->angleBetween(a, b), expected); + QCOMPARE(QGuiApplication::primaryScreen()->angleBetween(b, a), (360 - expected) % 360); } void tst_QScreen::transformBetween_data() @@ -149,6 +154,12 @@ void tst_QScreen::transformBetween_data() << uint(Qt::LandscapeOrientation) << rect << QTransform(-1, 0, 0, -1, rect.width(), rect.height()); + + QTest::newRow("Landscape Primary") + << uint(Qt::LandscapeOrientation) + << uint(Qt::PrimaryOrientation) + << rect + << QGuiApplication::primaryScreen()->transformBetween(Qt::LandscapeOrientation, QGuiApplication::primaryScreen()->primaryOrientation(), rect); } void tst_QScreen::transformBetween() @@ -161,7 +172,7 @@ void tst_QScreen::transformBetween() Qt::ScreenOrientation a = Qt::ScreenOrientation(oa); Qt::ScreenOrientation b = Qt::ScreenOrientation(ob); - QCOMPARE(QScreen::transformBetween(a, b, rect), expected); + QCOMPARE(QGuiApplication::primaryScreen()->transformBetween(a, b, rect), expected); } void tst_QScreen::orientationChange() @@ -169,10 +180,10 @@ void tst_QScreen::orientationChange() QScreen *screen = QGuiApplication::primaryScreen(); QWindowSystemInterface::handleScreenOrientationChange(screen, Qt::LandscapeOrientation); - QTRY_COMPARE(screen->currentOrientation(), Qt::LandscapeOrientation); + QTRY_COMPARE(screen->orientation(), Qt::LandscapeOrientation); QWindowSystemInterface::handleScreenOrientationChange(screen, Qt::PortraitOrientation); - QTRY_COMPARE(screen->currentOrientation(), Qt::PortraitOrientation); + QTRY_COMPARE(screen->orientation(), Qt::PortraitOrientation); } #include <tst_qscreen.moc> diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index ac8c8f9b20e8b2732eca89ffb8999107ac38403e..d0d2ce1e1dfc11186f246ef0ee41c35d710ef9cc 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -57,6 +57,7 @@ private slots: void touchToMouseTranslation(); void mouseToTouchTranslation(); void mouseToTouchLoop(); + void orientation(); void initTestCase() { touchDevice = new QTouchDevice; @@ -481,5 +482,22 @@ void tst_QWindow::mouseToTouchLoop() qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false); } +void tst_QWindow::orientation() +{ + QWindow window; + window.setGeometry(80, 80, 40, 40); + window.create(); + + window.reportContentOrientationChange(Qt::PortraitOrientation); + QCOMPARE(window.contentOrientation(), Qt::PortraitOrientation); + + window.reportContentOrientationChange(Qt::PrimaryOrientation); + QCOMPARE(window.contentOrientation(), window.screen()->primaryOrientation()); + + QVERIFY(!window.requestWindowOrientation(Qt::LandscapeOrientation) || window.windowOrientation() == Qt::LandscapeOrientation); + QVERIFY(!window.requestWindowOrientation(Qt::PortraitOrientation) || window.windowOrientation() == Qt::PortraitOrientation); + QVERIFY(!window.requestWindowOrientation(Qt::PrimaryOrientation) || window.windowOrientation() == window.screen()->primaryOrientation()); +} + #include <tst_qwindow.moc> QTEST_MAIN(tst_QWindow);