display(iOS): fix scaling issue for external displays

This commit is contained in:
osy
2026-01-19 10:54:44 -08:00
parent 286f7b43fa
commit 2cc156c9b5
4 changed files with 27 additions and 19 deletions
@@ -167,8 +167,8 @@ NS_AVAILABLE_IOS(13.4)
// Then we need to find out if the pointer is in the actual display area or outside
CGPoint location = [self.mtkView convertPoint:[request location] fromView:nil];
CGPoint translated = location;
translated.x = CGPointToPixel(translated.x);
translated.y = CGPointToPixel(translated.y);
translated.x = CGPointToPixel(self.view, translated.x);
translated.y = CGPointToPixel(self.view, translated.y);
if ([self isPointOnVMDisplay:translated]) {
// move vm cursor, hide iOS cursor
@@ -69,18 +69,26 @@ NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_END
static inline CGFloat CGPointToPixel(CGFloat point) {
static inline CGFloat CGPointToPixel(UIView * _Nonnull view, CGFloat point) {
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION
return point * 2.0;
#else
return point * [UIScreen mainScreen].nativeScale; // FIXME: multiple screens?
UIScreen *screen = view.window.screen;
if (!screen) {
screen = [UIScreen mainScreen];
}
return point * screen.nativeScale;
#endif
}
static inline CGFloat CGPixelToPoint(CGFloat pixel) {
static inline CGFloat CGPixelToPoint(UIView * _Nonnull view, CGFloat pixel) {
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION
return pixel / 2.0;
#else
return pixel / [UIScreen mainScreen].nativeScale; // FIXME: multiple screens?
UIScreen *screen = view.window.screen;
if (!screen) {
screen = [UIScreen mainScreen];
}
return pixel / screen.nativeScale;
#endif
}
@@ -315,8 +315,8 @@ static CGRect CGRectClipToBounds(CGRect rect1, CGRect rect2) {
if (sender.state != UIGestureRecognizerStateCancelled) {
CGPoint translation = [sender translationInView:sender.view];
CGPoint viewport = self.renderer.viewportOrigin;
viewport.x = CGPointToPixel(translation.x) + self.lastTwoPanOrigin.x;
viewport.y = CGPointToPixel(translation.y) + self.lastTwoPanOrigin.y;
viewport.x = CGPointToPixel(self.view, translation.x) + self.lastTwoPanOrigin.x;
viewport.y = CGPointToPixel(self.view, translation.y) + self.lastTwoPanOrigin.y;
self.renderer.viewportOrigin = [self clipDisplayToView:viewport];
// persist this change in viewState
self.delegate.displayOrigin = self.renderer.viewportOrigin;
@@ -362,8 +362,8 @@ static CGRect CGRectClipToBounds(CGRect rect1, CGRect rect2) {
- (CGPoint)moveMouseAbsolute:(CGPoint)location {
CGPoint translated = location;
translated.x = CGPointToPixel(translated.x);
translated.y = CGPointToPixel(translated.y);
translated.x = CGPointToPixel(self.view, translated.x);
translated.y = CGPointToPixel(self.view, translated.y);
translated = [self clipCursorToDisplay:translated];
if (!self.vmInput.serverModeCursor) {
[self.vmInput sendMousePosition:self.mouseButtonDown absolutePoint:translated];
@@ -375,8 +375,8 @@ static CGRect CGRectClipToBounds(CGRect rect1, CGRect rect2) {
}
- (CGPoint)moveMouseRelative:(CGPoint)translation {
translation.x = CGPointToPixel(translation.x) / self.renderer.viewportScale;
translation.y = CGPointToPixel(translation.y) / self.renderer.viewportScale;
translation.x = CGPointToPixel(self.view, translation.x) / self.renderer.viewportScale;
translation.y = CGPointToPixel(self.view, translation.y) / self.renderer.viewportScale;
if (self.vmInput.serverModeCursor) {
[self.vmInput sendMouseMotion:self.mouseButtonDown relativePoint:translation];
} else {
@@ -386,7 +386,7 @@ static CGRect CGRectClipToBounds(CGRect rect1, CGRect rect2) {
}
- (CGPoint)moveMouseScroll:(CGPoint)translation {
translation.y = CGPointToPixel(translation.y) / kScrollSpeedReduction;
translation.y = CGPointToPixel(self.view, translation.y) / kScrollSpeedReduction;
if (self.isInvertScroll) {
translation.y = -translation.y;
}
@@ -478,7 +478,7 @@ static CGRect CGRectClipToBounds(CGRect rect1, CGRect rect2) {
CGFloat scaling;
if (!self.delegate.qemuDisplayIsNativeResolution) {
// will be undo in `-setDisplayScaling:origin:`
scaling = CGPixelToPoint(CGPointToPixel(self.delegate.displayScale) * sender.scale);
scaling = CGPixelToPoint(self.view, CGPointToPixel(self.view, self.delegate.displayScale) * sender.scale);
} else {
scaling = self.delegate.displayScale * sender.scale;
}
@@ -205,8 +205,8 @@ static const NSInteger kResizeTimeoutSecs = 5;
- (CGSize)convertSizeToNative:(CGSize)size {
if (self.delegate.qemuDisplayIsNativeResolution) {
size.width = CGPointToPixel(size.width);
size.height = CGPointToPixel(size.height);
size.width = CGPointToPixel(self.view, size.width);
size.height = CGPointToPixel(self.view, size.height);
}
return size;
}
@@ -239,7 +239,7 @@ static const NSInteger kResizeTimeoutSecs = 5;
- (void)setDisplayScaling:(CGFloat)scaling origin:(CGPoint)origin {
self.renderer.viewportOrigin = origin;
if (!self.delegate.qemuDisplayIsNativeResolution) {
scaling = CGPointToPixel(scaling);
scaling = CGPointToPixel(self.view, scaling);
}
if (scaling) { // cannot be zero
self.renderer.viewportScale = scaling;
@@ -279,8 +279,8 @@ static const NSInteger kResizeTimeoutSecs = 5;
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION
CGSize minSize = displaySize;
if (self.delegate.qemuDisplayIsNativeResolution) {
minSize.width = CGPixelToPoint(minSize.width);
minSize.height = CGPixelToPoint(minSize.height);
minSize.width = CGPixelToPoint(self.view, minSize.width);
minSize.height = CGPixelToPoint(self.view, minSize.height);
}
CGSize maxSize = CGSizeMake(UIProposedSceneSizeNoPreference, UIProposedSceneSizeNoPreference);
UIWindowSceneGeometryPreferencesVision *geoPref = [[UIWindowSceneGeometryPreferencesVision alloc] initWithSize:minSize];