Made window orientation API more flexible.

Previously we only had QWindow::setOrientation() which was a hint about
the orientation the window's contents were rendered in.

However, it's necessary to separate between the orientation
corresponding to the window buffer layout and orientation of the
contents. A game for example might typically want to use a landscape
buffer even on a portrait device. Thus, we replace
QWindow::orientation() with QWindow::reportContentOrientationChange() and
QWindow::requestWindowOrientation().

Change-Id: I1f07362192daf36c45519cb05b43ac352f1945b5
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
This commit is contained in:
Samuel Rødal 2012-01-13 10:31:11 +01:00 committed by Qt by Nokia
parent b0a0403daf
commit b39df8bf92
19 changed files with 312 additions and 141 deletions

View File

@ -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();

View File

@ -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();
}

View File

@ -317,7 +317,7 @@ public:
Q_DECLARE_FLAGS(WindowStates, WindowState)
enum ScreenOrientation {
UnknownOrientation = 0x00000000,
PrimaryOrientation = 0x00000000,
PortraitOrientation = 0x00000001,
LandscapeOrientation = 0x00000002,
InvertedPortraitOrientation = 0x00000004,

View File

@ -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.

View File

@ -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);
}
QScreenOrientationChangeEvent event(s, s->currentOrientation());
void QGuiApplicationPrivate::reportScreenOrientationChange(QScreen *s)
{
emit s->orientationChanged(s->orientation());
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(

View File

@ -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);

View File

@ -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 device 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().
\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)

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -343,35 +343,36 @@ QRect QScreen::availableVirtualGeometry() const
}
/*!
\property QScreen::primaryOrientation
\brief the primary screen orientation
\property QScreen::orientation
\brief the screen orientation
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.
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.
\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

View File

@ -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);

View File

@ -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;

View File

@ -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.
The default value is Qt::UnknownOrientation.
\sa setOrientation(), QScreen::currentOrientation()
*/
Qt::ScreenOrientation QWindow::orientation() const
{
Q_D(const QWindow);
return d->orientation;
}
/*!
Set the orientation of the window's contents.
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::currentOrientation() but
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.
\sa QScreen::currentOrientation()
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::setOrientation(Qt::ScreenOrientation orientation)
void QWindow::reportContentOrientationChange(Qt::ScreenOrientation orientation)
{
Q_D(QWindow);
if (orientation == d->orientation)
return;
d->orientation = orientation;
if (d->platformWindow) {
d->platformWindow->setOrientation(orientation);
if (!d->platformWindow)
create();
Q_ASSERT(d->platformWindow);
d->contentOrientation = orientation;
d->platformWindow->handleContentOrientationChange(orientation);
}
emit orientationChanged(orientation);
/*!
Returns the actual content orientation.
This is the last value set with reportContentOrientationChange(),
except Qt::PrimaryOrientation gets converted to the screen's
primary orientation.
*/
Qt::ScreenOrientation QWindow::contentOrientation() const
{
Q_D(const QWindow);
return d->contentOrientation == Qt::PrimaryOrientation ? screen()->primaryOrientation() : d->contentOrientation;
}
/*!
Requests the given window orientation.
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 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 windowOrientation(), reportContentOrientationChange(), QScreen::orientation()
*/
bool QWindow::requestWindowOrientation(Qt::ScreenOrientation orientation)
{
Q_D(QWindow);
if (!d->platformWindow)
create();
Q_ASSERT(d->platformWindow);
d->windowOrientation = d->platformWindow->requestWindowOrientation(orientation);
return d->windowOrientation == 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

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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>

View File

@ -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);