iOS: Don't report UIDevice.currentDevice.orientation through QScreen

As of Qt 6 (3e12951c0b, the QScreen's
orientation() property is supposed to represent the orientation
of the screen from a window management perspective, and not the
orientation of the actual device, as in Qt 5 times.

For iOS, when the orientation of the app is locked to a orientation
via the Info.plist or [UIViewController supportedInterfaceOrientations],
the UIDevice API will keep reporting the actual orientation of the device,
which is wrong for the Qt 6 definition of the API.

We currently don't have an API in QScreen to represent the always
updating physical rotation of the device. For this use-case the
supported API is QOrientationReading in Qt Sensors.

[ChangeLog][iOS] QScreen::orientation() will no longer report the
device's physical orientation when orientation has been locked
to a subset of the available orientations, but will instead
match the primary orientation.

Task-number: QTBUG-38576
Task-number: QTBUG-121781
Change-Id: I251a039a618656466cbfd1d836a5b49a6be8e736
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
bb10
Tor Arne Vestbø 2024-04-08 20:25:46 +02:00
parent c0f6d10bc2
commit bc014d5fc7
2 changed files with 7 additions and 76 deletions

View File

@ -63,7 +63,6 @@ private:
uint m_physicalDpi;
#endif
QSizeF m_physicalSize;
QIOSOrientationListener *m_orientationListener = nullptr;
CADisplayLink *m_displayLink = nullptr;
};

View File

@ -107,50 +107,6 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
@end
// -------------------------------------------------------------------------
@interface QIOSOrientationListener : NSObject
@end
@implementation QIOSOrientationListener {
QIOSScreen *m_screen;
}
- (instancetype)initWithQIOSScreen:(QIOSScreen *)screen
{
self = [super init];
if (self) {
m_screen = screen;
#ifndef Q_OS_TVOS
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(orientationChanged:)
name:@"UIDeviceOrientationDidChangeNotification" object:nil];
#endif
}
return self;
}
- (void)dealloc
{
#ifndef Q_OS_TVOS
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:@"UIDeviceOrientationDidChangeNotification" object:nil];
#endif
[super dealloc];
}
- (void)orientationChanged:(NSNotification *)notification
{
Q_UNUSED(notification);
m_screen->updateProperties();
}
@end
#endif // !defined(Q_OS_VISIONOS)
// -------------------------------------------------------------------------
@ -235,8 +191,6 @@ QIOSScreen::QIOSScreen(UIScreen *screen)
}
}
m_orientationListener = [[QIOSOrientationListener alloc] initWithQIOSScreen:this];
m_displayLink = [m_uiScreen displayLinkWithBlock:^(CADisplayLink *) { deliverUpdateRequests(); }];
m_displayLink.paused = YES; // Enabled when clients call QWindow::requestUpdate()
[m_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
@ -250,7 +204,6 @@ QIOSScreen::~QIOSScreen()
{
[m_displayLink invalidate];
[m_orientationListener release];
[m_uiWindow release];
}
@ -423,34 +376,13 @@ Qt::ScreenOrientation QIOSScreen::nativeOrientation() const
Qt::ScreenOrientation QIOSScreen::orientation() const
{
#if defined(Q_OS_TVOS) || defined(Q_OS_VISIONOS)
return Qt::PrimaryOrientation;
#else
// Auxiliary screens are always the same orientation as their primary orientation
if (m_uiScreen != [UIScreen mainScreen])
return Qt::PrimaryOrientation;
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
// At startup, iOS will report an unknown orientation for the device, even
// if we've asked it to begin generating device orientation notifications.
// In this case we fall back to the status bar orientation, which reflects
// the orientation the application was started up in (which may not match
// the physical orientation of the device, but typically does unless the
// application has been locked to a subset of the available orientations).
if (deviceOrientation == UIDeviceOrientationUnknown && !qt_apple_isApplicationExtension())
deviceOrientation = UIDeviceOrientation(qt_apple_sharedApplication().statusBarOrientation);
// If the device reports face up or face down orientations, we can't map
// them to Qt orientations, so we pretend we're in the same orientation
// as before.
if (deviceOrientation == UIDeviceOrientationFaceUp || deviceOrientation == UIDeviceOrientationFaceDown) {
Q_ASSERT(screen());
return screen()->orientation();
}
return toQtScreenOrientation(deviceOrientation);
#endif
// We don't report UIDevice.currentDevice.orientation here,
// as that would report the actual orientation of the device,
// even if the orientation of the UI was locked to a subset
// of the possible orientations via the app's Info.plist or
// via [UIViewController supportedInterfaceOrientations].
return m_geometry.width() >= m_geometry.height() ?
Qt::LandscapeOrientation : Qt::PortraitOrientation;
}
QPixmap QIOSScreen::grabWindow(WId window, int x, int y, int width, int height) const