Orientation overview in Qt
- Auto-rotation: the process where the platform will read sensor data about the physical screen orientation and apply that to the screen properties, so that eg. a screen in a physical landscape orientation will have an observable width > height.
- Orientation-lock: More or less granular configuration of which orientations the platform is allowed to auto-rotate into
QScreen::nativeOrienation: the fixed standard-orientation of the physical screen, eg the orienation where the logo makes sense. Typically landscape for desktop screens. Never changes.
QScreen::primaryOrienation: the 'logical' orientation of the screen, computed from its geometry properties. Typically landscape or portrait, depending on the width and height ratio. A screen that auto-rotated due to sensor input of the physical screen will have a new primary orientation.
QScreen::orientation: the physical orientation of the screen, resulting from reading sensor data about the screen when the
orientationUpdateMaskhas been been set.
QScreen::orientationUpdateMask: limits which orientations are reflected in the orientation property. The default value is 0, meaning the
orientationproperty will not change. This allows Qt to tell the system that we are not interested in orientation sensor updates. If the system then does not require any sensor readings of its own (due to auto-rotation, eg), it can disable the sensor and save battery. This is why the default is 0.
QWindow::reportContentOrientation: allows the application to inform the system that the content is oriented differently then what you would expect from
QScreen::primaryOrienation, which allows the system to orient system-provided UI elements such as statusbars and system alert dialogs in the same orientation.
Note that we currenly have no API in Qt to configure auto-rotation (orientation-lock). This is partially because on both iOS and Android orientation-lock (or supported orientations) is a combination of build-system properties and runtime properties, which we haven't been able to unify as a single Qt API.
UC1: Application supports all orientations and will re-layout to available screen geometry
This scenario happens on eg. iOS, where the platform will by default auto-rotate to most orientations. During auto-rotation we reconfigure the QScreen, which then gets a new width and height (geometry), and in effect a new
orientation property will stay static (based on what the orientation of the device was at startup), unless the
orientationUpdateMask is set. If set (to match all orientations), the
orientation property will start reporting the same value as
primaryOrientation, since the two are in sync due to auto-rotation. This is convenience for using a
If the auto-rotation (supported orientations) have been configured in eg. Xcode to limit to only portrait and landscape, not the inverse counterparts, the
primaryOrientation property will only switch between the two former orientations, while the
orientation property will report changes for all orientations that are part of the
UC2: Application supports only a single orientation
An application may be designed for only a single orientation, typically portrait on a mobile device. In this case the system APIs are used to lock the orientation (limit the supported orientations), eg using Xcode/Info.plist for iOS.
primaryOrientation in this case stays in portrait, and never changes. The same goes for the
orientation propery, as the
orientationUpdateMask is by default 0. This allows the platform to ignore orientation sensor readings and possibly save battery.
UC3: Application supports multiple orientations, but want custom orientation transitions/animations
Auto-rotation by the system happens using system transitions/animations, typically a rotation of the whole window. In some cases (games eg.) it might be nicer to have a custom transition, eg. on individual items in the scene instead of the whole scene as one.
For this to work, step one is to disable auto-rotation, eg. by configuring supported orientation in Xcode/Info.plist for iOS, similar to
#UC2. This means the
primaryOrientation will be static (typically portrait).
Next, we set the
orientationUpdateMask so that we start reciving changes to the
orientation property. This could be done using
QOrientationSensor as well. Once we know the current physical orientation of the device, we apply a rotation transform with animation transition to eg. the individual items in the scene.
At this point the content of our application will rotate to match the physicall device orientation (using a cool custom animation), but any system UI elements such as the statusbar or system alert dialogs will pop up in portrait mode, since as far as the system knows, the screen is in portrait mode, as reflected by the
This is where
reportContentOrientation enters the picture. By reporting the true orientation of the content back to the system, it can adjust its UI elements to match our content orientation.
Q1: Why does not
orientationUpdateMaskhas been set? A change in
primaryOrientationmeans the system internally is checking the orientation sensor, so even if the application doesn't explicitly request updates to the orientation, we can still assume that the
orientationhas also changed. Or can we? Are there other ways the
primaryOrientationcan change were the physical orientation of the device stays the same?
A1: Discussed here: https://gist.github.com/torarnv/0c9d36108f838c7bac9c and here: https://codereview.qt-project.org/#/c/95661/.
Q2: What are the different states of the
A2: The property has the following behavior:
QScreenis constructed based on an added
QScreenPrivateconstructor will read out the orientation from the platform screen, and set that as the initial
filteredOrientation(falling back to the effective primary orientation if the platform screen returns
Qt::PrimaryOrientation). This initialization of
filteredOrienationis not filtered by any orientation update mask, so the platform screen is allowed to initialize the orientation to the actual physical orientation of the device.
QScreenconstruction, the getter for the property in
QScreenjust returns the internal
filteredOrientation, meaning the only way to update the orientation after a screen has been added is to call
QWindowSystemInterface::handleOrientationChange(). The new orientation will then only be reflected if the
orientationUpdateMaskmatches the new orientation.
- For every call to
setOrientationUpdateMaskthe internal orientation of the screen will be re-evaluated against the mask, and
filteredOrientationwill possibly be updated and a change signal emitted.