From 7c1f28037418bb58423dfc2d23ec76c8a4f490cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesu=CC=81s=20A=2E=20A=CC=81lvarez?= Date: Sat, 10 Feb 2024 12:15:01 +0100 Subject: [PATCH] keyboard for visionOS --- Mini vMac.xcodeproj/project.pbxproj | 22 ++++++ .../contents.xcworkspacedata | 7 ++ .../xcshareddata/Mini vMac.xcscmblueprint | 37 ++++++++++ Mini vMac/AppDelegate.m | 36 ++++++++++ .../KBCapsLock.imageset/Contents.json | 5 ++ .../KBCapsLock~ipad@2x 1.png | Bin 0 -> 317 bytes .../KBClearDown.imageset/Contents.json | 5 ++ .../KBClearDown~ipad@2x 1.png | Bin 0 -> 401 bytes .../KBClearUp.imageset/Contents.json | 5 ++ .../KBClearUp~ipad@2x 1.png | Bin 0 -> 563 bytes .../KBCommand.imageset/Contents.json | 5 ++ .../KBCommand@2x~ipad 1.png | Bin 0 -> 1031 bytes .../KBDeleteDown.imageset/Contents.json | 5 ++ .../KBDeleteDown~ipad@2x 1.png | Bin 0 -> 526 bytes .../KBDeleteUp.imageset/Contents.json | 5 ++ .../KBDeleteUp~ipad@2x 1.png | Bin 0 -> 726 bytes .../Contents.json | 5 ++ .../KBForwardDeleteDown~ipad@2x 1.png | Bin 0 -> 526 bytes .../KBForwardDeleteUp.imageset/Contents.json | 5 ++ .../KBForwardDeleteUp~ipad@2x 1.png | Bin 0 -> 718 bytes .../KBHide.imageset/Contents.json | 6 ++ .../KBHide.imageset/KBHide~ipad 2.png | Bin 0 -> 242 bytes .../KBHide.imageset/KBHide~ipad@2x 1.png | Bin 0 -> 438 bytes .../KBKey.imageset/Contents.json | 19 +++++ .../KBKey.imageset/KBKey@2x~ipad-2 1.png | Bin 0 -> 634 bytes .../KBKeyDark.imageset/Contents.json | 19 +++++ .../KBKeyDark@2x~ipad-1 1.png | Bin 0 -> 636 bytes .../KBNumPad.imageset/Contents.json | 5 ++ .../KBNumPad.imageset/KBNumPad@2x~ipad 1.png | Bin 0 -> 178 bytes .../KBOption.imageset/Contents.json | 5 ++ .../KBOption.imageset/KBOption@2x~ipad 1.png | Bin 0 -> 365 bytes .../KBShiftDown.imageset/Contents.json | 5 ++ .../KBShiftDown~ipad@2x 1.png | Bin 0 -> 274 bytes .../KBShiftUp.imageset/Contents.json | 5 ++ .../KBShiftUp~ipad@2x 1.png | Bin 0 -> 467 bytes .../Reset.imageset/Contents.json | 15 ++-- .../Settings.imageset/Contents.json | 15 ++-- Mini vMac/DefaultSceneDelegate.swift | 35 +++++++++ Mini vMac/Info.plist | 23 ++++++ Mini vMac/KBKeyboardView.m | 5 ++ Mini vMac/KeyboardSceneDelegate.swift | 32 +++++++++ Mini vMac/Mini vMac-Bridging-Header.h | 8 +++ Mini vMac/SettingsViewController.m | 4 ++ Mini vMac/ViewController.h | 8 +++ Mini vMac/ViewController.m | 67 ++++++++++++++++-- Mini vMac/VisionSupport.swift | 66 +++++++++++++++++ 46 files changed, 466 insertions(+), 18 deletions(-) create mode 100644 Mini vMac.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Mini vMac.xcodeproj/project.xcworkspace/xcshareddata/Mini vMac.xcscmblueprint create mode 100644 Mini vMac/Assets.xcassets/KBCapsLock.imageset/KBCapsLock~ipad@2x 1.png create mode 100644 Mini vMac/Assets.xcassets/KBClearDown.imageset/KBClearDown~ipad@2x 1.png create mode 100644 Mini vMac/Assets.xcassets/KBClearUp.imageset/KBClearUp~ipad@2x 1.png create mode 100644 Mini vMac/Assets.xcassets/KBCommand.imageset/KBCommand@2x~ipad 1.png create mode 100644 Mini vMac/Assets.xcassets/KBDeleteDown.imageset/KBDeleteDown~ipad@2x 1.png create mode 100644 Mini vMac/Assets.xcassets/KBDeleteUp.imageset/KBDeleteUp~ipad@2x 1.png create mode 100644 Mini vMac/Assets.xcassets/KBForwardDeleteDown.imageset/KBForwardDeleteDown~ipad@2x 1.png create mode 100644 Mini vMac/Assets.xcassets/KBForwardDeleteUp.imageset/KBForwardDeleteUp~ipad@2x 1.png create mode 100644 Mini vMac/Assets.xcassets/KBHide.imageset/KBHide~ipad 2.png create mode 100644 Mini vMac/Assets.xcassets/KBHide.imageset/KBHide~ipad@2x 1.png create mode 100644 Mini vMac/Assets.xcassets/KBKey.imageset/KBKey@2x~ipad-2 1.png create mode 100644 Mini vMac/Assets.xcassets/KBKeyDark.imageset/KBKeyDark@2x~ipad-1 1.png create mode 100644 Mini vMac/Assets.xcassets/KBNumPad.imageset/KBNumPad@2x~ipad 1.png create mode 100644 Mini vMac/Assets.xcassets/KBOption.imageset/KBOption@2x~ipad 1.png create mode 100644 Mini vMac/Assets.xcassets/KBShiftDown.imageset/KBShiftDown~ipad@2x 1.png create mode 100644 Mini vMac/Assets.xcassets/KBShiftUp.imageset/KBShiftUp~ipad@2x 1.png create mode 100644 Mini vMac/DefaultSceneDelegate.swift create mode 100644 Mini vMac/KeyboardSceneDelegate.swift create mode 100644 Mini vMac/Mini vMac-Bridging-Header.h create mode 100644 Mini vMac/VisionSupport.swift diff --git a/Mini vMac.xcodeproj/project.pbxproj b/Mini vMac.xcodeproj/project.pbxproj index d0b0be1..d21034a 100644 --- a/Mini vMac.xcodeproj/project.pbxproj +++ b/Mini vMac.xcodeproj/project.pbxproj @@ -58,6 +58,9 @@ 28C67BE92AC49E46000C7540 /* Icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 283423EE1CFA329C0088B634 /* Icon@3x.png */; }; 28C67BF62AC49FA1000C7540 /* MacII-512x384.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 28C67BEE2AC49E46000C7540 /* MacII-512x384.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 28CE8ED61CD4F56C00FE25A8 /* ScreenView.m in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8ED51CD4F56C00FE25A8 /* ScreenView.m */; }; + 28D3C6152B7681420079E915 /* VisionSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D3C6142B7681420079E915 /* VisionSupport.swift */; }; + 28D3C6172B76B8970079E915 /* DefaultSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D3C6162B76B8970079E915 /* DefaultSceneDelegate.swift */; }; + 28D3C61B2B7781700079E915 /* KeyboardSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D3C61A2B7781700079E915 /* KeyboardSceneDelegate.swift */; }; 28D5A3FD1CD6868F001A33F6 /* TouchScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D5A3FC1CD6868E001A33F6 /* TouchScreen.m */; }; 28E3B7DF251D0F13007C273F /* MOUSEMDV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7CC251D0F12007C273F /* MOUSEMDV.c */; }; 28E3B7E0251D0F13007C273F /* MOUSEMDV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28E3B7CC251D0F12007C273F /* MOUSEMDV.c */; }; @@ -282,6 +285,10 @@ 28CE8ECB1CD4CDC500FE25A8 /* MYOSGLUE.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYOSGLUE.m; sourceTree = ""; }; 28CE8ED41CD4F56C00FE25A8 /* ScreenView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreenView.h; sourceTree = ""; }; 28CE8ED51CD4F56C00FE25A8 /* ScreenView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScreenView.m; sourceTree = ""; }; + 28D3C6132B7681420079E915 /* Mini vMac-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Mini vMac-Bridging-Header.h"; sourceTree = ""; }; + 28D3C6142B7681420079E915 /* VisionSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisionSupport.swift; sourceTree = ""; }; + 28D3C6162B76B8970079E915 /* DefaultSceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultSceneDelegate.swift; sourceTree = ""; }; + 28D3C61A2B7781700079E915 /* KeyboardSceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardSceneDelegate.swift; sourceTree = ""; }; 28D5A3FB1CD6868E001A33F6 /* TouchScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TouchScreen.h; sourceTree = ""; }; 28D5A3FC1CD6868E001A33F6 /* TouchScreen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TouchScreen.m; sourceTree = ""; }; 28E3B7CC251D0F12007C273F /* MOUSEMDV.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MOUSEMDV.c; sourceTree = ""; }; @@ -611,6 +618,7 @@ 28BA89841CE73E7200A98104 /* TrackPad.m */, 28F676C61CD15E0B00FC6FA6 /* ViewController.h */, 28F676C71CD15E0B00FC6FA6 /* ViewController.m */, + 28D3C6142B7681420079E915 /* VisionSupport.swift */, 28848B601CDE97D600B86C45 /* InsertDiskViewController.h */, 28848B611CDE97D600B86C45 /* InsertDiskViewController.m */, 28848B631CDE97E900B86C45 /* SettingsViewController.h */, @@ -627,6 +635,8 @@ 28F6B4CE1CF77099002D76D0 /* compat.m */, 283CA9821DF47AF300B33D5E /* BTCMouse.h */, 283422EF1CF8F33A0088B634 /* Emulator Bundles */, + 28D3C6162B76B8970079E915 /* DefaultSceneDelegate.swift */, + 28D3C61A2B7781700079E915 /* KeyboardSceneDelegate.swift */, ); path = "Mini vMac"; sourceTree = ""; @@ -634,6 +644,7 @@ 28F676C01CD15E0B00FC6FA6 /* Supporting Files */ = { isa = PBXGroup; children = ( + 28D3C6132B7681420079E915 /* Mini vMac-Bridging-Header.h */, 28F6B4551CF07C9A002D76D0 /* libhfs */, 28F6B4541CF07C8D002D76D0 /* libmfs */, 28F6B4531CF07C83002D76D0 /* libres */, @@ -950,6 +961,7 @@ 28F676BC1CD15E0B00FC6FA6 = { CreatedOnToolsVersion = 7.3; DevelopmentTeam = UJXNDZ5TNU; + LastSwiftMigration = 1520; }; 28F6B48D1CF07DDD002D76D0 = { CreatedOnToolsVersion = 7.3.1; @@ -1287,14 +1299,17 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 28D3C6152B7681420079E915 /* VisionSupport.swift in Sources */, 28BA897E1CE7315400A98104 /* KBKey.m in Sources */, 28BA89851CE73E7200A98104 /* TrackPad.m in Sources */, + 28D3C6172B76B8970079E915 /* DefaultSceneDelegate.swift in Sources */, 28CE8ED61CD4F56C00FE25A8 /* ScreenView.m in Sources */, 28848B651CDE97E900B86C45 /* SettingsViewController.m in Sources */, 28BA89881CE73FBC00A98104 /* MNVMApplication.m in Sources */, 28F6B4CF1CF77099002D76D0 /* compat.m in Sources */, 28F6B4521CF07C48002D76D0 /* UIImage+DiskImageIcon.m in Sources */, 28BA897F1CE7315400A98104 /* KBKeyboardLayout.m in Sources */, + 28D3C61B2B7781700079E915 /* KeyboardSceneDelegate.swift in Sources */, 28848B621CDE97D600B86C45 /* InsertDiskViewController.m in Sources */, 28F676C81CD15E0B00FC6FA6 /* ViewController.m in Sources */, 28D5A3FD1CD6868F001A33F6 /* TouchScreen.m in Sources */, @@ -1902,6 +1917,7 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 14; @@ -1921,6 +1937,9 @@ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_OBJC_BRIDGING_HEADER = "Mini vMac/Mini vMac-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2,7"; }; name = Debug; @@ -1929,6 +1948,7 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 14; @@ -1948,6 +1968,8 @@ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_OBJC_BRIDGING_HEADER = "Mini vMac/Mini vMac-Bridging-Header.h"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2,7"; }; name = Release; diff --git a/Mini vMac.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Mini vMac.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..33dea32 --- /dev/null +++ b/Mini vMac.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Mini vMac.xcodeproj/project.xcworkspace/xcshareddata/Mini vMac.xcscmblueprint b/Mini vMac.xcodeproj/project.xcworkspace/xcshareddata/Mini vMac.xcscmblueprint new file mode 100644 index 0000000..3dde625 --- /dev/null +++ b/Mini vMac.xcodeproj/project.xcworkspace/xcshareddata/Mini vMac.xcscmblueprint @@ -0,0 +1,37 @@ +{ + "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "9C19786155D97B8ED78AB84AFAAA50249126341A", + "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { + + }, + "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { + "9C19786155D97B8ED78AB84AFAAA50249126341A" : 0, + "F2E8D120DACD6BF5E1EFFA012C92CE6FA0E44B4C" : 0, + "45D35ABA2A883CFEB6F6014CF9723CDA568B602B" : 0 + }, + "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "A273011D-9F4F-4F93-8287-77CF2E175709", + "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { + "9C19786155D97B8ED78AB84AFAAA50249126341A" : "minivmac4ios\/", + "F2E8D120DACD6BF5E1EFFA012C92CE6FA0E44B4C" : "minivmac4ios\/libres\/", + "45D35ABA2A883CFEB6F6014CF9723CDA568B602B" : "minivmac4ios\/libmfs\/" + }, + "DVTSourceControlWorkspaceBlueprintNameKey" : "Mini vMac", + "DVTSourceControlWorkspaceBlueprintVersion" : 204, + "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "Mini vMac.xcodeproj", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/zydeco\/libmfs.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "45D35ABA2A883CFEB6F6014CF9723CDA568B602B" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:zydeco\/minivmac4ios.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "9C19786155D97B8ED78AB84AFAAA50249126341A" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/zydeco\/libres.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "F2E8D120DACD6BF5E1EFFA012C92CE6FA0E44B4C" + } + ] +} \ No newline at end of file diff --git a/Mini vMac/AppDelegate.m b/Mini vMac/AppDelegate.m index 378a72a..317d054 100644 --- a/Mini vMac/AppDelegate.m +++ b/Mini vMac/AppDelegate.m @@ -10,6 +10,7 @@ #import "AppDelegate.h" #import "SettingsViewController.h" #import "InsertDiskViewController.h" +#import "ViewController.h" static AppDelegate *sharedAppDelegate = nil; static NSObject *sharedEmulator = nil; @@ -106,6 +107,9 @@ NSString *DocumentsChangedNotification = @"documentsChanged"; [self showAlertWithTitle:title message:message]; }; sharedEmulator.dataPath = self.documentsPath; +#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1 + [ViewController adjustToScreenSize]; +#endif return sharedEmulator != nil; } @@ -311,4 +315,36 @@ NSString *DocumentsChangedNotification = @"documentsChanged"; return YES; } +#pragma mark - Making a Scene + +- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options { + for (NSUserActivity *activity in options.userActivities) { + if ([activity.activityType isEqualToString:@"net.namedfork.keyboard"]) { + return [UISceneConfiguration configurationWithName:@"Keyboard" sessionRole:UIWindowSceneSessionRoleApplication]; + } + } + if (![self hasDefaultScene]) { + return [UISceneConfiguration configurationWithName:@"Default" sessionRole:UIWindowSceneSessionRoleApplication]; + } + return nil; +} + + +- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions { + // if only keyboard is left, show default view again + if (![self hasDefaultScene]) { + UISceneSessionActivationRequest *request = [UISceneSessionActivationRequest requestWithRole:UIWindowSceneSessionRoleApplication]; + [application activateSceneSessionForRequest:request errorHandler:nil]; + } +} + +- (BOOL)hasDefaultScene { + for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) { + if ([scene.session.configuration.name isEqualToString:@"Default"]) { + return YES; + } + } + return NO; +} + @end diff --git a/Mini vMac/Assets.xcassets/KBCapsLock.imageset/Contents.json b/Mini vMac/Assets.xcassets/KBCapsLock.imageset/Contents.json index 68dd648..a3d53fe 100644 --- a/Mini vMac/Assets.xcassets/KBCapsLock.imageset/Contents.json +++ b/Mini vMac/Assets.xcassets/KBCapsLock.imageset/Contents.json @@ -23,6 +23,11 @@ "filename" : "KBCapsLock~ipad@2x.png", "idiom" : "ipad", "scale" : "2x" + }, + { + "filename" : "KBCapsLock~ipad@2x 1.png", + "idiom" : "vision", + "scale" : "2x" } ], "info" : { diff --git a/Mini vMac/Assets.xcassets/KBCapsLock.imageset/KBCapsLock~ipad@2x 1.png b/Mini vMac/Assets.xcassets/KBCapsLock.imageset/KBCapsLock~ipad@2x 1.png new file mode 100644 index 0000000000000000000000000000000000000000..10327318570fefcb44cea4da7146209153ea5bf7 GIT binary patch literal 317 zcmV-D0mA-?P)I#}f?6>!fiE!6D;U?K3Zs*4sS P00000NkvXXu0mjf2k(8^ literal 0 HcmV?d00001 diff --git a/Mini vMac/Assets.xcassets/KBClearDown.imageset/Contents.json b/Mini vMac/Assets.xcassets/KBClearDown.imageset/Contents.json index b6f380c..0cb3e83 100644 --- a/Mini vMac/Assets.xcassets/KBClearDown.imageset/Contents.json +++ b/Mini vMac/Assets.xcassets/KBClearDown.imageset/Contents.json @@ -23,6 +23,11 @@ "filename" : "KBClearDown~ipad@2x.png", "idiom" : "ipad", "scale" : "2x" + }, + { + "filename" : "KBClearDown~ipad@2x 1.png", + "idiom" : "vision", + "scale" : "2x" } ], "info" : { diff --git a/Mini vMac/Assets.xcassets/KBClearDown.imageset/KBClearDown~ipad@2x 1.png b/Mini vMac/Assets.xcassets/KBClearDown.imageset/KBClearDown~ipad@2x 1.png new file mode 100644 index 0000000000000000000000000000000000000000..d35aecbae14edea563d0746c5c3cc329c713d6f2 GIT binary patch literal 401 zcmV;C0dD?@P)7{=iz=w)QQDC>Aza%J)p^6?Y0=S^bEmVn} zJnQYi$f-XNefDP54wOV~K9Q=4GT#oAL}fmaDv2^b0FV=9z8xruGCv&9=YW1Vpv>11 zmHAUnRT7o?kx?a4nNLzBQJt?P>hmSh4y>2?lCa(mER^|@u+R>Cwq&i$XT+K%pDTcX z`4O7`!Rt`qHTOe-`*fi|$Kg=mFwuQOElYJlY}(*b1!FR5y|!48%% zfuY3BP$sa19o(R*50H2fMA^WI084+6c^@j8%axi_GuIXz;Y>a_0AO^-k zSP(noAS{TTaS#^7&KL*-VqrvtK>9Qz^a+485lxI=q)*p3zK>6&nds~K6)+%X0&p+} z#7sCC17arZj2+qMAjJ6ksXyl=#Q6Es8qFE@Bf`P#=M1BbNPsjUMI8nZA_LT2gx?y* z5F%sL{Tn`NSU`v@Q1?f;rePByvPs?7;E0AKA(B-05m=@n!)$zKHW_s<19+_Q5rgoV zK|E6LW0d8Tbo!9l9-qZSb(UBTD7&a?$r7=S#Z00fang@TEM^@MS*lug(Ue1aHhz~9 zhiJcsaKU$=Ov@nsVOhR`<#v8WT=Bmy1|O_f8P8i)O7N;yM-G znO~=PL{Ej4L|mnw!Mq}VGr4Ar>?`rPk=1jQh@BL!7oQtZeKYD5duztpB9>F%pk5Zw zDZD4nSMDWowPqYGeo#?nf6-Kxy=HQCRIKAI z>5u!wb_P+-G`4ZLvz=G9`$b&kyoQT-y5@W5I?9e_Q&H~EdJ&at1+)TM0j+>mKr5gX z&W<*8nOG6LGu(lln!xVMzLSKykLa%&Ty&=r9|9N&w^gQQWKWytsisEr1im zcL0NE6Z`zB0qcku513BGl7DKzlp>Y`78Eh7a+`@5USr>j!;~9U#D>5qA~sd-4Dq36 zJSgr^Zc!1l0DL0OQ0^IVqh_2azE*Az(P40aTf}>YP~U{w#DSWzp@@0Z*TZAt6@^Vi zoT8qd9ub{p(Ts8YEZ#PhdUg?Uh(g6ZA{Hw-VR4jZZ6zfabsE2mR}H4XczzH++DNTI z9Hz7QK)KojI>*pzE$eg9VHP#k)g|Ia;{m9c*>fU(HjCado-ahaYau-WjN)vOdau0| z{VXCrb(0g_<2w=Yks0)^@x3g);vaUhYrHQaI&7_uNnI~BYj?7d^ogMy=x3?fgJxE0 zTKl`-TfXwD+ih=LePa}xy1`4n^sYx7X-djBRvb6}yRT>%NmNkLS(VbMdd;e`{S|1R64z zZQSJ>rdIpHJMMCVb@WE2K1Dpo1h&JpKwtnjF#+!x18`&vUoj!<6&-M3oT?Xgh8mfm z>!pn%E0c7+xN5L7nQxeocMdC4_>KvE53w+vpO^^tfsD)yUathqj!bX(N*Z$o{d>x& zB8IUnMiphe$6#Ly^QEIN0U(!{MV|vev3tM*eqn@FLOj8uhf3Fgh5W`y^H>{Cu;_E} z+yWN!N0QqU1bsYUXU2tF+tNCfN}D3Z%@b(^#(feL08%nM7@Ely3U>; z>kW7T1;mm9V(tM40@dpYbm2{a`W$k^1Yj^<1JiqWVgdl8`RZ367m5i0z$iVzB2yEH zCwvJ=uO$#?q?}NRUE=AVV;IS2DWEv(F?#wB35?*A5b&N-Dl+Kf2^ExTzhp3ikC+IT zfx&!;O#g+942mq_ITi*+lyC_v19*=KeH-BaO;|`)`iGqGj0R9s!rKr73UHt=uS3%B zOKW{Qv*} literal 0 HcmV?d00001 diff --git a/Mini vMac/Assets.xcassets/KBDeleteUp.imageset/Contents.json b/Mini vMac/Assets.xcassets/KBDeleteUp.imageset/Contents.json index e46a6d3..83412c4 100644 --- a/Mini vMac/Assets.xcassets/KBDeleteUp.imageset/Contents.json +++ b/Mini vMac/Assets.xcassets/KBDeleteUp.imageset/Contents.json @@ -23,6 +23,11 @@ "filename" : "KBDeleteUp~ipad@2x.png", "idiom" : "ipad", "scale" : "2x" + }, + { + "filename" : "KBDeleteUp~ipad@2x 1.png", + "idiom" : "vision", + "scale" : "2x" } ], "info" : { diff --git a/Mini vMac/Assets.xcassets/KBDeleteUp.imageset/KBDeleteUp~ipad@2x 1.png b/Mini vMac/Assets.xcassets/KBDeleteUp.imageset/KBDeleteUp~ipad@2x 1.png new file mode 100644 index 0000000000000000000000000000000000000000..ab4c7efc308d50875b3cc2fcd2fdc838568aa36d GIT binary patch literal 726 zcmV;{0xA88P)D{a5cU&`zx9>pMkNYqrVtJgga7R}YtN>@ zW&}!rUS{=uIzlYLRLiV?4{Otea4;|e6fqNC6h=4{AOVuhj5p-lR3RL;5rRid37#ND znK@tVgrh1#GAkHI2)05P#|o0MB(uobBu4~TWiGve5DQ_WIe)bhk%MqdNr3TWSQtVu zf8+ItiE`3$H334|#2a&M#&Y!UL6n1UErNhQcq%#>G1 zwg=@3DFjyyGvhwi`U~R{Nd#4A`Q-z91LSS~VqlETX8nZ}*g*O0c_9!+c|Mud8&ODu z_!ZED62)n=@);Bj5ylOw`+6^&GOPZeF_P}y_{t8tP>14#_s@twa&qgKr`_OpyusOiWVB(Qy;fEFki$$KQ=Jz^vt>B(m#gjF#WPh3SpS{2hV zG8qYRRm{XdB@%MNY+SjHguH6z;KC~;^wlsIM}8s^td0fxfS?l=k&!ASvV0d)HKHNF$7m;!)G?|!XL zKN$ef>jOym%Vh1(vE>q1uGUY|{vokk-=9L2{tuHhf60m|b9swx$|&ZCLjRkIB!fh_ zU+H@I8=3wmW5~dV$n>Mh$nA*qqi|qn1o|J0#F171R}U?DAF_S~2J%AGe>3Z$35P<` ze_+!MxB3@Rhfh3@!U0y~8am=eqwPt-_02#m2?7!%O;LJg!sfQ&tkjNlQ%*ei_j{Id^gGZy|6 zV;p}cTe{L%#0VnL6~PD=k!Hl$k1%WzOV#dbA~b|mYJUk>F~-;-Mv|>z2tlopV8}Rt zFl-Q!tp3T+5Y`Y0#*BkZvQXJ))gB>#BYcQyw_BIC>SGz z;3K1`+!NabVL@2UYF`)yxuLG|nwo;JAVd=B1EYZa()mbZ5QI5F{^E_1pKI#$C)$7> zp(p76YF<9BsFR;*3mSw0!3!fFm*j1#z5Pddqyumyre$$a2pw&|)CfV#Sc+MhTo6KM zyRUbP8HFNf7^7HBn&AT>1iFGb!akD+qC0;kKZipETc+k-ke;c{bb>5{^G*b~t+p!> zT$WJu4oEUjdpC}qxrocF;?ykf7b`P zVO1ke`ApbLbzD@R`RwNb&prI>XWU~CGpUJjIU@U}3+XKJGynhq07*qoM6N<$g6XV9 ADF6Tf literal 0 HcmV?d00001 diff --git a/Mini vMac/Assets.xcassets/KBHide.imageset/Contents.json b/Mini vMac/Assets.xcassets/KBHide.imageset/Contents.json index f01cb0e..7838a85 100644 --- a/Mini vMac/Assets.xcassets/KBHide.imageset/Contents.json +++ b/Mini vMac/Assets.xcassets/KBHide.imageset/Contents.json @@ -1,6 +1,7 @@ { "images" : [ { + "filename" : "KBHide~ipad 2.png", "idiom" : "iphone", "scale" : "1x" }, @@ -23,6 +24,11 @@ "filename" : "KBHide~ipad@2x.png", "idiom" : "ipad", "scale" : "2x" + }, + { + "filename" : "KBHide~ipad@2x 1.png", + "idiom" : "vision", + "scale" : "2x" } ], "info" : { diff --git a/Mini vMac/Assets.xcassets/KBHide.imageset/KBHide~ipad 2.png b/Mini vMac/Assets.xcassets/KBHide.imageset/KBHide~ipad 2.png new file mode 100644 index 0000000000000000000000000000000000000000..2c28bb8161c328465ee3c3090f2209c7a5829158 GIT binary patch literal 242 zcmVAAK?10so0~r8!S{m$e9q#eud)nOH{~xIfQL(s? za%n*23_BrIRuCX$QGwZXuk8HGru&!Qhj+87URhbesUej!=8S1)qGEAuT1N+m}wp;OU sJ$8h(EW)l{6_F?jp(Ig36IuMo6J>&oFEHQLQUCw|07*qoM6N<$g2^>vMF0Q* literal 0 HcmV?d00001 diff --git a/Mini vMac/Assets.xcassets/KBHide.imageset/KBHide~ipad@2x 1.png b/Mini vMac/Assets.xcassets/KBHide.imageset/KBHide~ipad@2x 1.png new file mode 100644 index 0000000000000000000000000000000000000000..faa6196dd6c9c4abfb56b023eb3d4b5571eb95ce GIT binary patch literal 438 zcmV;n0ZIOeP)lJT173m3wUa)@7r^F9Ps|AOLy|eE6-*evm?T*j9 zJGwKo5XK{qIGX|T*j(=<)fuA8R06F1qRezWpYJBv7<+YrX1;QSvhvx;FD zMg)&XY+_J0@(_;*W9Afs@P#Y*=ocTC`GO#vXUrT#G%r|7Kdj{$qB+FaIYLp3edGYW zvY!t+SCJ!3gcPr| z;M}aNEHpu&6i_`7Ad3T)rKhK7WMlvtnVFeD5~v_MI~&Lb3Z|x}#>K@&L`1l`xyj1P z0%d{rhK7a$Nhv8Qpc){<#>NIn0)dZ@4}<|EB_$<+q>zx1t*vcHNC?mnpiw{rfdH-s z!f-yE<^p6nmjw9*GYI*0tUhu3@tY5yBsyPtKmGjW>o>2wkFUG8TzdTa)0eMrp4~jU zvcm48^ai%1cLwbo0rR9n)KWteJ2xD^_55v+jhk<@W6jp@vW zBF8`8|9!M{t=sD7Wikc~%^Uy!&(~;Wl3bul(_msl;Yy1ECoH@4Faogn= z9~!y&{x8rx@WrTCScy%_EyW^^i(8}ckK{h5s*JBfYEe$zxibV_oD>yS-PnGw&g0MB z{~l9ZJVB_Xbsn!UUzMJZ#EY5PeNQK4EV$~zDHN45=f#4{M>|b37bc!8oxu>9EwxQe zP&Mqy9_Mv=e(N5wObhb8#b!CHEa;@s)_b*a&aBy${ zieLgaH#eXzAPJEIGF-sG6%2q}2mtbc!cI<3c6N4_mX`YZ`l6zuKtZ6r=H})=Qb0fe z!qw2w0CIuAz`y{)0FwOt{6LbImse9$6KDd^9A{@|ho>2wkFUG8TzdTa)0eMrp4~jUvcm48^ai%1cLwbo0rR9n z)KWteJCEOb{x-yLJIxocIru~i9`CARx$|tsL*HgK)F21w#1gmY)s^cbx zQ;pe_6s4CoWOXm9@E7DSk`UVaX?f87I-$#fuP^LA{UEzP`^~?DN(Z(Yb#e-_d;2Z1 zj%#J@Df}Y2&nYS*TU90Nkkso50yif6+?il;=-x)a$Q^1p^(_y)5*4N){GkyRCT64QB!fy^X}fDA}E+$bZtTY*`Ao=EMY-C zueoYhy(&~(eWmLABX%YEV!_I%jGbQpSFGASGwZZy5X-#3e_G^t%VU&%8T|J}bi5I( mZg-jfvTWTh+v4VGz3;qhSv(Rrs#7vRk>Tm;=d#Wzp$Pz2#N?;| literal 0 HcmV?d00001 diff --git a/Mini vMac/Assets.xcassets/KBNumPad.imageset/Contents.json b/Mini vMac/Assets.xcassets/KBNumPad.imageset/Contents.json index ddc90b7..564f943 100644 --- a/Mini vMac/Assets.xcassets/KBNumPad.imageset/Contents.json +++ b/Mini vMac/Assets.xcassets/KBNumPad.imageset/Contents.json @@ -23,6 +23,11 @@ "filename" : "KBNumPad@2x~ipad.png", "idiom" : "ipad", "scale" : "2x" + }, + { + "filename" : "KBNumPad@2x~ipad 1.png", + "idiom" : "vision", + "scale" : "2x" } ], "info" : { diff --git a/Mini vMac/Assets.xcassets/KBNumPad.imageset/KBNumPad@2x~ipad 1.png b/Mini vMac/Assets.xcassets/KBNumPad.imageset/KBNumPad@2x~ipad 1.png new file mode 100644 index 0000000000000000000000000000000000000000..332186cd398d62c71033771e54b1829746148fcb GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^`ao>N!2%@H(!7#@RHdhjV@L(#+Z*OgOo|LH7vl?+ z)_!TYbDr(cXxMpO;?bLyF)?JHE36Wxuz{`Wo~s^=3AWmm|K|}-d>#Zd&~Fx*H0b{ z!!QiPFbrX=AkXe%n1y}Y9eC*>e^|#i2NsNdhaGsw=5&DUrgp#x2fP!on%e)aM=sZ~ zg#Xz?t=+xCX)9=zgfvtfXF?KQqvDAKeC9kVq9kE}Ehv~vnIx1m7X_Ockc4PdoaeJ7 zJVV7B37F(0Dl#PD11nLmlmF(wJ`P;o~BzH%8A;gT@KZWPR>KoTlhh=TR> zNJ2a+EPRp#D=MrK@DU3t5+$LB4JcSdwImcW2L*c>mV`)DT;;1I+((7K1dMY81+&PL zgcgGTyNh_mYC8Dl&}?|gS*CRZ;DvSo#A*l3V4mI0LMSr~!!W)B9|?gPuf!AC00000 LNkvXXu0mjfqXdyH literal 0 HcmV?d00001 diff --git a/Mini vMac/Assets.xcassets/KBShiftDown.imageset/Contents.json b/Mini vMac/Assets.xcassets/KBShiftDown.imageset/Contents.json index e6d47eb..c309287 100644 --- a/Mini vMac/Assets.xcassets/KBShiftDown.imageset/Contents.json +++ b/Mini vMac/Assets.xcassets/KBShiftDown.imageset/Contents.json @@ -23,6 +23,11 @@ "filename" : "KBShiftDown~ipad@2x.png", "idiom" : "ipad", "scale" : "2x" + }, + { + "filename" : "KBShiftDown~ipad@2x 1.png", + "idiom" : "vision", + "scale" : "2x" } ], "info" : { diff --git a/Mini vMac/Assets.xcassets/KBShiftDown.imageset/KBShiftDown~ipad@2x 1.png b/Mini vMac/Assets.xcassets/KBShiftDown.imageset/KBShiftDown~ipad@2x 1.png new file mode 100644 index 0000000000000000000000000000000000000000..7f5a483ad901fbc28bdeb5b90d315d4829666749 GIT binary patch literal 274 zcmV+t0qy>YP)UbY!8ZYO=t_i+hLGR;h0eq(lzEs ztTG`n0+C-~u7tn{gaczNe*z*S5c%c*8Dr5(D2zbl7nnDpFajYm#+)$lIp#?Sj4>mK z&oF^d7=ch2Zz4a%{wAh`yaOW;A~V*B7G^9E3L_9IGs=YHM~q;P;QRq>+>s5OxFaV} zapwqpaZN=_Vc;DVq#y+;$lD;|MMJiOkgbNS2O(<>nefn?cwmCq4wp215L*7A;gX7$ YB62H!o3H2bZ~y=R07*qoM6N<$f+0+5v;Y7A literal 0 HcmV?d00001 diff --git a/Mini vMac/Assets.xcassets/KBShiftUp.imageset/Contents.json b/Mini vMac/Assets.xcassets/KBShiftUp.imageset/Contents.json index 6a811f9..09f9e53 100644 --- a/Mini vMac/Assets.xcassets/KBShiftUp.imageset/Contents.json +++ b/Mini vMac/Assets.xcassets/KBShiftUp.imageset/Contents.json @@ -23,6 +23,11 @@ "filename" : "KBShiftUp~ipad@2x.png", "idiom" : "ipad", "scale" : "2x" + }, + { + "filename" : "KBShiftUp~ipad@2x 1.png", + "idiom" : "vision", + "scale" : "2x" } ], "info" : { diff --git a/Mini vMac/Assets.xcassets/KBShiftUp.imageset/KBShiftUp~ipad@2x 1.png b/Mini vMac/Assets.xcassets/KBShiftUp.imageset/KBShiftUp~ipad@2x 1.png new file mode 100644 index 0000000000000000000000000000000000000000..8ee79237e26b84af901382a01f273fd823cd2776 GIT binary patch literal 467 zcmV;^0WAKBP)x|!FT zCnW5VhAwO|q89Y_5s7-xfT^Y)kf3`Swph)GTGZEjM0Ur)R8x0|=%!_QXjYG + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).DefaultSceneDelegate + + + UISceneConfigurationName + Keyboard + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).KeyboardSceneDelegate + + + + diff --git a/Mini vMac/KBKeyboardView.m b/Mini vMac/KBKeyboardView.m index 8e21f81..b124bd0 100644 --- a/Mini vMac/KBKeyboardView.m +++ b/Mini vMac/KBKeyboardView.m @@ -126,8 +126,13 @@ keyFrame.origin.x += safeAreaInsets.left; } if (scancode == VKC_HIDE) { +#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1 + // close window to hide + return; +#else key = [[KBHideKey alloc] initWithFrame:keyFrame]; [key addTarget:self action:@selector(hideKeyboard:) forControlEvents:UIControlEventTouchUpInside]; +#endif } else if (scancode == VKC_SHIFT_CAPS) { key = [[KBShiftCapsKey alloc] initWithFrame:keyFrame]; key.scancode = KC_SHIFT; diff --git a/Mini vMac/KeyboardSceneDelegate.swift b/Mini vMac/KeyboardSceneDelegate.swift new file mode 100644 index 0000000..b780975 --- /dev/null +++ b/Mini vMac/KeyboardSceneDelegate.swift @@ -0,0 +1,32 @@ +// +// KeyboardSceneDelegate.swift +// Mini vMac +// +// Created by Jesús A. Álvarez on 2024-02-10. +// Copyright © 2024 namedfork. All rights reserved. +// + +import UIKit + +class KeyboardSceneDelegate: UIResponder, UIWindowSceneDelegate { + var window: UIWindow? + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + guard let windowScene = scene as? UIWindowScene else { + fatalError("Expected scene of type UIWindowScene but got an unexpected type") + } + guard let mainViewController = AppDelegate.sharedInstance().window.rootViewController as? ViewController else { + fatalError("No main view controller") + } + + let size = mainViewController.keyboardViewController.preferredContentSize + windowScene.sizeRestrictions?.minimumSize = size + windowScene.sizeRestrictions?.maximumSize = size + window = UIWindow(windowScene: windowScene) + + if let window { + window.rootViewController = mainViewController.keyboardViewController + window.makeKeyAndVisible() + } + } +} diff --git a/Mini vMac/Mini vMac-Bridging-Header.h b/Mini vMac/Mini vMac-Bridging-Header.h new file mode 100644 index 0000000..0a5bcae --- /dev/null +++ b/Mini vMac/Mini vMac-Bridging-Header.h @@ -0,0 +1,8 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "ViewController.h" +#import "AppDelegate.h" +#import "KBKeyboardView.h" +#import "KBKeyboardLayout.h" diff --git a/Mini vMac/SettingsViewController.m b/Mini vMac/SettingsViewController.m index 7367226..ffd65a6 100644 --- a/Mini vMac/SettingsViewController.m +++ b/Mini vMac/SettingsViewController.m @@ -177,7 +177,11 @@ typedef enum : NSInteger { case SettingsSectionMachine: return machineList.count; case SettingsSectionAbout: +#if !defined(TARGET_OS_VISION) || TARGET_OS_VISION == 0 return aboutItems.count + 1; +#else + return aboutItems.count; +#endif default: return 1; } diff --git a/Mini vMac/ViewController.h b/Mini vMac/ViewController.h index e94b244..38d7e95 100644 --- a/Mini vMac/ViewController.h +++ b/Mini vMac/ViewController.h @@ -18,6 +18,14 @@ - (IBAction)showGestureHelp:(id)sender; - (IBAction)hideGestureHelp:(id)sender; +- (void)showKeyboard:(id)sender; @end +#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1 +@interface ViewController (VisionSupport) +@property (nonatomic, readonly) UIViewController* keyboardViewController; +- (void)initXr; ++ (void)adjustToScreenSize; +@end +#endif diff --git a/Mini vMac/ViewController.m b/Mini vMac/ViewController.m index 0d5cb9b..be6fdcc 100644 --- a/Mini vMac/ViewController.m +++ b/Mini vMac/ViewController.m @@ -29,6 +29,7 @@ API_AVAILABLE(ios(13.4)) KBKeyboardView *keyboardView; UISwipeGestureRecognizer *showKeyboardGesture, *hideKeyboardGesture, *insertDiskGesture, *showSettingsGesture; UIControl *pointingDeviceView; + UIViewController *_keyboardViewController; id interaction; } @@ -43,20 +44,55 @@ API_AVAILABLE(ios(13.4)) - (void)viewDidLoad { [super viewDidLoad]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(emulatorDidShutDown:) name:[AppDelegate sharedEmulator].shutdownNotification object:nil]; + +#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1 + [self initXr]; +#else + [self scheduleHelpPresentationIfNeededAfterDelay:6.0]; + [self installGestures]; +#endif +} + +#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1 +- (UIViewController *)keyboardViewController { + if (keyboardView == nil) { + [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"keyboardLayout" options:0 context:NULL]; + KBKeyboardLayout *layout = [self keyboardLayout]; + CGSize keyboardSize = CGSizeZero; + for (NSValue *size in layout.availableSizes) { + if (size.CGSizeValue.width > keyboardSize.width) { + keyboardSize = size.CGSizeValue; + } + } + keyboardView = [[KBKeyboardView alloc] initWithFrame:CGRectMake(0, 0, keyboardSize.width, keyboardSize.height)]; + keyboardView.layout = layout; + keyboardView.delegate = self; + } + if (_keyboardViewController == nil) { + _keyboardViewController = [UIViewController alloc]; + _keyboardViewController.view = keyboardView; + _keyboardViewController.preferredContentSize = keyboardView.frame.size; + } else if (_keyboardViewController.view != keyboardView) { + _keyboardViewController.view = keyboardView; + } + return _keyboardViewController; +} +#endif + +- (void)installGestures { [self installKeyboardGestures]; insertDiskGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(showInsertDisk:)]; insertDiskGesture.direction = UISwipeGestureRecognizerDirectionLeft; insertDiskGesture.numberOfTouchesRequired = 2; [self.view addGestureRecognizer:insertDiskGesture]; - + showSettingsGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(showSettings:)]; showSettingsGesture.direction = UISwipeGestureRecognizerDirectionRight; showSettingsGesture.numberOfTouchesRequired = 2; [self.view addGestureRecognizer:showSettingsGesture]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(emulatorDidShutDown:) name:[AppDelegate sharedEmulator].shutdownNotification object:nil]; - - [self scheduleHelpPresentationIfNeededAfterDelay:6.0]; + } - (void)showSettings:(id)sender { @@ -149,6 +185,11 @@ API_AVAILABLE(ios(13.4)) - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (object == [NSUserDefaults standardUserDefaults]) { if ([keyPath isEqualToString:@"keyboardLayout"] && keyboardView != nil) { +#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1 + // FIXME: do this nicelier + keyboardView = nil; + [self keyboardViewController]; +#else BOOL keyboardWasVisible = self.keyboardVisible; [self setKeyboardVisible:NO animated:NO]; [keyboardView removeFromSuperview]; @@ -156,6 +197,7 @@ API_AVAILABLE(ios(13.4)) if (keyboardWasVisible) { [self setKeyboardVisible:YES animated:NO]; } +#endif } else if ([keyPath isEqualToString:@"trackpad"]) { [self setUpPointingDevice]; } @@ -215,7 +257,9 @@ API_AVAILABLE(ios(13.4)) #pragma mark - Gesture Help - (void)showGestureHelp:(id)sender { +#if !defined(TARGET_OS_VISION) || TARGET_OS_VISION == 0 [self setGestureHelpHidden:NO]; +#endif } - (void)hideGestureHelp:(id)sender { @@ -271,7 +315,11 @@ API_AVAILABLE(ios(13.4)) } - (BOOL)isKeyboardVisible { +#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1 + return _keyboardViewController.view.window != nil; +#else return keyboardView != nil && CGRectIntersectsRect(keyboardView.frame, self.view.bounds) && !keyboardView.hidden; +#endif } - (void)setKeyboardVisible:(BOOL)keyboardVisible { @@ -291,6 +339,13 @@ API_AVAILABLE(ios(13.4)) return; } +#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1 + if (visible) { + UISceneSessionActivationRequest *request = [UISceneSessionActivationRequest requestWithRole:UIWindowSceneSessionRoleApplication]; + request.userActivity = [[NSUserActivity alloc] initWithActivityType:@"net.namedfork.keyboard"]; + [[UIApplication sharedApplication] activateSceneSessionForRequest:request errorHandler:nil]; + } // only show, no hide +#else if (visible) { [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"keyboardLayout" options:0 context:NULL]; [self loadKeyboardView]; @@ -324,7 +379,7 @@ API_AVAILABLE(ios(13.4)) keyboardView.hidden = YES; } } - +#endif } - (void)loadKeyboardView { diff --git a/Mini vMac/VisionSupport.swift b/Mini vMac/VisionSupport.swift new file mode 100644 index 0000000..1379de9 --- /dev/null +++ b/Mini vMac/VisionSupport.swift @@ -0,0 +1,66 @@ +// +// VisionSupport.swift +// Mini vMac +// +// Created by Jesús A. Álvarez on 2024-02-09. +// Copyright © 2024 namedfork. All rights reserved. +// + +import Foundation +import UIKit +import SwiftUI + +extension ViewController { +#if os(visionOS) + @objc + func initXr() { + ViewController.adjustToScreenSize() + ornaments = [ + UIHostingOrnament(sceneAnchor: .bottom, contentAlignment: .center) { + VStack { + Spacer(minLength: 80.0) + HStack { + Button(action: { + AppDelegate.sharedInstance().showSettings(self) + }, label: { + Image(systemName: "gear") + }).glassBackgroundEffect() + + Button(action: { + AppDelegate.sharedInstance().showInsertDisk(self) + }, label: { + Image(systemName: "opticaldiscdrive") + }).glassBackgroundEffect() + + Button(action: { + self.showKeyboard(self) + }, label: { + Image(systemName: "keyboard") + }).glassBackgroundEffect() + }.padding(.all) + .glassBackgroundEffect() + } + } + ] + } + + @objc + static func adjustToScreenSize() { + let screenSize = AppDelegate.sharedEmulator().screenSize + guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { + return + } + let minSize = screenSize + let defaultSize = screenSize.applying(.init(scaleX: 2.0, y: 2.0)) + let maxSize = screenSize.applying(.init(scaleX: 3.0, y: 3.0)) + windowScene.sizeRestrictions?.minimumSize = minSize + windowScene.sizeRestrictions?.maximumSize = maxSize + windowScene.requestGeometryUpdate(UIWindowScene.GeometryPreferences.Vision( + size: defaultSize, + minimumSize: minSize, + maximumSize: maxSize, + resizingRestrictions: .uniform + )) + } +#endif +}