summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/ios/quiview.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/ios/quiview.mm')
-rw-r--r--src/plugins/platforms/ios/quiview.mm96
1 files changed, 36 insertions, 60 deletions
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 979de6a313..cc4b92b92b 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -10,6 +10,7 @@
#include "qiosscreen.h"
#include "qioswindow.h"
#include "qiosinputcontext.h"
+#include "quiwindow.h"
#ifndef Q_OS_TVOS
#include "qiosmenu.h"
#endif
@@ -53,7 +54,6 @@ inline ulong getTimeStamp(UIEvent *event)
@implementation QUIView {
QHash<NSUInteger, QWindowSystemInterface::TouchPoint> m_activeTouches;
UITouch *m_activePencilTouch;
- int m_nextTouchId;
NSMutableArray<UIAccessibilityElement *> *m_accessibleElements;
UIPanGestureRecognizer *m_scrollGestureRecognizer;
CGPoint m_lastScrollCursorPos;
@@ -62,7 +62,7 @@ inline ulong getTimeStamp(UIEvent *event)
+ (void)load
{
-#ifndef Q_OS_TVOS
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 11)) {
// iOS 11 handles this though [UIView safeAreaInsetsDidChange], but there's no signal for
// the corresponding top and bottom layout guides that we use on earlier versions. Note
@@ -92,7 +92,16 @@ inline ulong getTimeStamp(UIEvent *event)
{
if (self = [self initWithFrame:window->geometry().toCGRect()]) {
self.platformWindow = window;
+
+ if (isQtApplication())
+ self.hidden = YES;
+
m_accessibleElements = [[NSMutableArray<UIAccessibilityElement *> alloc] init];
+
+#ifndef Q_OS_TVOS
+ self.multipleTouchEnabled = YES;
+#endif
+
m_scrollGestureRecognizer = [[UIPanGestureRecognizer alloc]
initWithTarget:self
action:@selector(handleScroll:)];
@@ -109,6 +118,7 @@ inline ulong getTimeStamp(UIEvent *event)
m_lastScrollCursorPos = CGPointZero;
[self addGestureRecognizer:m_scrollGestureRecognizer];
+ // Set up layer
if ([self.layer isKindOfClass:CAMetalLayer.class]) {
QWindow *window = self.platformWindow->window();
if (QColorSpace colorSpace = window->format().colorSpace(); colorSpace.isValid()) {
@@ -119,17 +129,8 @@ inline ulong getTimeStamp(UIEvent *event)
qCDebug(lcQpaWindow) << "Set" << self << "color space to" << metalLayer.colorspace;
}
}
- }
-
- return self;
-}
-
-- (instancetype)initWithFrame:(CGRect)frame
-{
- if ((self = [super initWithFrame:frame])) {
#if QT_CONFIG(opengl)
- if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
- // Set up EAGL layer
+ else if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer);
eaglLayer.opaque = TRUE;
eaglLayer.drawableProperties = @{
@@ -139,37 +140,13 @@ inline ulong getTimeStamp(UIEvent *event)
}
#endif
- if (isQtApplication())
- self.hidden = YES;
-
-#ifndef Q_OS_TVOS
- self.multipleTouchEnabled = YES;
+#if defined(Q_OS_VISIONOS)
+ // Although the "Drawing sharp layer-based content in visionOS" docs
+ // claim that by default a CALayer rasterizes at a 2x scale this does
+ // not seem to be the case in practice. So we explicitly set the view's
+ // scale factor based on the screen, where we hard-code it to 2.0.
+ self.contentScaleFactor = self.platformWindow->screen()->devicePixelRatio();
#endif
-
- if (qEnvironmentVariableIntValue("QT_IOS_DEBUG_WINDOW_MANAGEMENT")) {
- static CGFloat hue = 0.0;
- CGFloat lastHue = hue;
- for (CGFloat diff = 0; diff < 0.1 || diff > 0.9; diff = fabs(hue - lastHue))
- hue = drand48();
-
- #define colorWithBrightness(br) \
- [UIColor colorWithHue:hue saturation:0.5 brightness:br alpha:1.0].CGColor
-
- self.layer.borderColor = colorWithBrightness(1.0);
- self.layer.borderWidth = 1.0;
- }
-
- if (qEnvironmentVariableIsSet("QT_IOS_DEBUG_WINDOW_SAFE_AREAS")) {
- UIView *safeAreaOverlay = [[UIView alloc] initWithFrame:CGRectZero];
- [safeAreaOverlay setBackgroundColor:[UIColor colorWithRed:0.3 green:0.7 blue:0.9 alpha:0.3]];
- [self addSubview:safeAreaOverlay];
-
- safeAreaOverlay.translatesAutoresizingMaskIntoConstraints = NO;
- [safeAreaOverlay.topAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor].active = YES;
- [safeAreaOverlay.leftAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.leftAnchor].active = YES;
- [safeAreaOverlay.rightAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.rightAnchor].active = YES;
- [safeAreaOverlay.bottomAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.bottomAnchor].active = YES;
- }
}
return self;
@@ -198,6 +175,7 @@ inline ulong getTimeStamp(UIEvent *event)
return description;
}
+#if !defined(Q_OS_VISIONOS)
- (void)willMoveToWindow:(UIWindow *)newWindow
{
// UIKIt will normally set the scale factor of a view to match the corresponding
@@ -207,6 +185,7 @@ inline ulong getTimeStamp(UIEvent *event)
// FIXME: Allow the scale factor to be customized through QSurfaceFormat.
}
+#endif
- (void)didAddSubview:(UIView *)subview
{
@@ -264,6 +243,9 @@ inline ulong getTimeStamp(UIEvent *event)
Q_UNUSED(layer);
Q_ASSERT(layer == self.layer);
+ if (!self.platformWindow)
+ return;
+
[self sendUpdatedExposeEvent];
}
@@ -305,7 +287,7 @@ inline ulong getTimeStamp(UIEvent *event)
// blocked by this guard.
FirstResponderCandidate firstResponderCandidate(self);
- qImDebug() << "self:" << self << "first:" << [UIResponder currentFirstResponder];
+ qImDebug() << "self:" << self << "first:" << [UIResponder qt_currentFirstResponder];
if (![super becomeFirstResponder]) {
qImDebug() << self << "was not allowed to become first responder";
@@ -316,7 +298,7 @@ inline ulong getTimeStamp(UIEvent *event)
}
if (qGuiApp->focusWindow() != self.platformWindow->window())
- QWindowSystemInterface::handleWindowActivated(self.platformWindow->window(), Qt::ActiveWindowFocusReason);
+ QWindowSystemInterface::handleFocusWindowChanged(self.platformWindow->window(), Qt::ActiveWindowFocusReason);
else
qImDebug() << self.platformWindow->window() << "already active, not sending window activation";
@@ -344,7 +326,7 @@ inline ulong getTimeStamp(UIEvent *event)
- (BOOL)resignFirstResponder
{
- qImDebug() << "self:" << self << "first:" << [UIResponder currentFirstResponder];
+ qImDebug() << "self:" << self << "first:" << [UIResponder qt_currentFirstResponder];
if (![super resignFirstResponder])
return NO;
@@ -353,7 +335,7 @@ inline ulong getTimeStamp(UIEvent *event)
UIResponder *newResponder = FirstResponderCandidate::currentCandidate();
if ([self responderShouldTriggerWindowDeactivation:newResponder])
- QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason);
+ QWindowSystemInterface::handleFocusWindowChanged(nullptr, Qt::ActiveWindowFocusReason);
return YES;
}
@@ -367,7 +349,7 @@ inline ulong getTimeStamp(UIEvent *event)
if ([self isFirstResponder])
return YES;
- UIResponder *firstResponder = [UIResponder currentFirstResponder];
+ UIResponder *firstResponder = [UIResponder qt_currentFirstResponder];
if ([firstResponder isKindOfClass:[QIOSTextInputResponder class]]
&& [firstResponder nextResponder] == self)
return YES;
@@ -518,7 +500,10 @@ inline ulong getTimeStamp(UIEvent *event)
{
Q_ASSERT(!m_activeTouches.contains(touch.hash));
#endif
- m_activeTouches[touch.hash].id = m_nextTouchId++;
+ // Use window-independent touch identifiers, so that
+ // multi-touch works across windows.
+ static quint16 nextTouchId = 0;
+ m_activeTouches[touch.hash].id = nextTouchId++;
#if QT_CONFIG(tabletevent)
}
#endif
@@ -560,9 +545,6 @@ inline ulong getTimeStamp(UIEvent *event)
// tvOS only supports single touch
m_activeTouches.clear();
#endif
-
- if (m_activeTouches.isEmpty() && !m_activePencilTouch)
- m_nextTouchId = 0;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
@@ -595,7 +577,6 @@ inline ulong getTimeStamp(UIEvent *event)
qWarning("Subset of active touches cancelled by UIKit");
m_activeTouches.clear();
- m_nextTouchId = 0;
m_activePencilTouch = nil;
ulong timestamp = event ? getTimeStamp(event) : ([[NSProcessInfo processInfo] systemUptime] * 1000);
@@ -699,7 +680,7 @@ inline ulong getTimeStamp(UIEvent *event)
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
-#ifndef Q_OS_TVOS
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
// Check first if QIOSMenu should handle the action before continuing up the responder chain
return [QIOSMenu::menuActionTarget() targetForAction:action withSender:sender] != 0;
#else
@@ -712,7 +693,7 @@ inline ulong getTimeStamp(UIEvent *event)
- (id)forwardingTargetForSelector:(SEL)selector
{
Q_UNUSED(selector);
-#ifndef Q_OS_TVOS
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
return QIOSMenu::menuActionTarget();
#else
return nil;
@@ -828,14 +809,9 @@ inline ulong getTimeStamp(UIEvent *event)
return nil;
}
-- (UIEdgeInsets)qt_safeAreaInsets
-{
- return self.safeAreaInsets;
-}
-
@end
-#ifdef Q_OS_IOS
+#if QT_CONFIG(metal)
@implementation QUIMetalView
+ (Class)layerClass