visionOS: make keyboard resizable ±25%

This commit is contained in:
Jesús A. Álvarez 2024-02-10 21:37:13 +01:00
parent 7a93412c3f
commit 043c20b645
2 changed files with 38 additions and 5 deletions

View File

@ -16,19 +16,22 @@
#define KC_CONTROL 59 #define KC_CONTROL 59
@implementation KBKeyboardView { @implementation KBKeyboardView {
NSMutableArray *keyPlanes; NSMutableArray *keyPlanes, *emptyKeyPlanes;
NSMutableSet *modifiers; NSMutableSet *modifiers;
NSMutableIndexSet *keysDown; NSMutableIndexSet *keysDown;
CGAffineTransform defaultKeyTransform; CGAffineTransform defaultKeyTransform;
CGFloat fontSize; CGFloat fontSize;
CGSize selectedSize; CGSize selectedSize;
UIEdgeInsets safeAreaInsets; UIEdgeInsets safeAreaInsets;
CGSize intrinsicSize;
} }
- (instancetype)initWithFrame:(CGRect)frame safeAreaInsets:(UIEdgeInsets)insets { - (instancetype)initWithFrame:(CGRect)frame safeAreaInsets:(UIEdgeInsets)insets {
self = [super initWithFrame:frame]; self = [super initWithFrame:frame];
if (self) { if (self) {
safeAreaInsets = insets; safeAreaInsets = insets;
intrinsicSize = frame.size;
#if !defined(TARGET_OS_VISION) || TARGET_OS_VISION == 0
if (@available(iOS 13.0, *)) { if (@available(iOS 13.0, *)) {
self.backgroundColor = [UIColor clearColor]; self.backgroundColor = [UIColor clearColor];
UIVisualEffectView *backgroundView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleSystemThickMaterial]]; UIVisualEffectView *backgroundView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleSystemThickMaterial]];
@ -37,8 +40,10 @@
} else { } else {
self.backgroundColor = [UIColor colorWithRed:0xEB / 255.0 green:0xF0 / 255.0 blue:0xF7 / 255.0 alpha:0.9]; self.backgroundColor = [UIColor colorWithRed:0xEB / 255.0 green:0xF0 / 255.0 blue:0xF7 / 255.0 alpha:0.9];
} }
#endif
modifiers = [NSMutableSet setWithCapacity:4]; modifiers = [NSMutableSet setWithCapacity:4];
keysDown = [NSMutableIndexSet indexSet]; keysDown = [NSMutableIndexSet indexSet];
self.autoresizesSubviews = NO;
} }
return self; return self;
} }
@ -47,10 +52,29 @@
return [self initWithFrame:frame safeAreaInsets:UIEdgeInsetsZero]; return [self initWithFrame:frame safeAreaInsets:UIEdgeInsetsZero];
} }
- (CGSize)intrinsicContentSize {
return intrinsicSize;
}
- (BOOL)isCompactKeyboardSize:(CGSize)size { - (BOOL)isCompactKeyboardSize:(CGSize)size {
return size.width < 768.0; return size.width < 768.0;
} }
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
- (void)layoutSubviews {
// TODO: optimize this if needed
CGSize size = self.bounds.size;
CGFloat scale = size.width / intrinsicSize.width;
CGAffineTransform transform = CGAffineTransformMakeScale(scale, scale);
if (!CGAffineTransformEqualToTransform(transform, defaultKeyTransform)) {
defaultKeyTransform = transform;
keyPlanes = emptyKeyPlanes.mutableCopy;
fontSize = 30.0 * scale;
[self switchToKeyPlane:0];
}
}
#endif
- (CGSize)findBestSizeForWidth:(CGFloat)preferredWidth inArray:(NSArray<NSValue*>*)sizes { - (CGSize)findBestSizeForWidth:(CGFloat)preferredWidth inArray:(NSArray<NSValue*>*)sizes {
CGSize selectedSize = CGSizeZero; CGSize selectedSize = CGSizeZero;
for (NSValue *key in sizes) { for (NSValue *key in sizes) {
@ -116,7 +140,8 @@
for (int i = 0; i < numberOfKeyPlanes; i++) { for (int i = 0; i < numberOfKeyPlanes; i++) {
[keyPlanes addObject:[NSNull null]]; [keyPlanes addObject:[NSNull null]];
} }
emptyKeyPlanes = keyPlanes.mutableCopy;
[self switchToKeyPlane:0]; [self switchToKeyPlane:0];
} }

View File

@ -19,9 +19,17 @@ class KeyboardSceneDelegate: UIResponder, UIWindowSceneDelegate {
fatalError("No main view controller") fatalError("No main view controller")
} }
let size = mainViewController.keyboardViewController.preferredContentSize let defaultSize = mainViewController.keyboardViewController.preferredContentSize
windowScene.sizeRestrictions?.minimumSize = size let minSize = defaultSize.applying(.init(scaleX: 0.75, y: 0.75))
windowScene.sizeRestrictions?.maximumSize = size let maxSize = defaultSize.applying(.init(scaleX: 1.25, y: 1.25))
windowScene.sizeRestrictions?.minimumSize = minSize
windowScene.sizeRestrictions?.maximumSize = maxSize
windowScene.requestGeometryUpdate(UIWindowScene.GeometryPreferences.Vision(
size: defaultSize,
minimumSize: minSize,
maximumSize: maxSize,
resizingRestrictions: .uniform
))
window = UIWindow(windowScene: windowScene) window = UIWindow(windowScene: windowScene)
if let window { if let window {