Compare commits
28 Commits
003c075108
...
fdbf6aab7e
Author | SHA1 | Date | |
---|---|---|---|
|
fdbf6aab7e | ||
|
19c0072d4c | ||
|
da3f639ef2 | ||
|
65d377884b | ||
|
2dab9cca28 | ||
|
fcb71f79ff | ||
|
2ccef4e3a6 | ||
|
fca6943bfe | ||
|
afef4e5b25 | ||
|
772ce2c326 | ||
|
ef6ef61037 | ||
|
3b4244e4e3 | ||
|
c1c7c93c6a | ||
|
61dc6ddcd7 | ||
|
0204043e10 | ||
|
043c20b645 | ||
|
7a93412c3f | ||
|
e1adde78f0 | ||
|
632f01f169 | ||
|
ed99d1bbfb | ||
|
53cb92f4ef | ||
|
22256824d2 | ||
|
3b96faf502 | ||
|
33e01e0847 | ||
|
7c1f280374 | ||
|
4aef44bf76 | ||
|
cf86226c6b | ||
|
8f4bc46d12 |
|
@ -30,7 +30,6 @@
|
|||
28BA89801CE7315400A98104 /* KBKeyboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 28BA89791CE7315400A98104 /* KBKeyboardView.m */; };
|
||||
28BA89821CE7336500A98104 /* Keyboard Layouts in Resources */ = {isa = PBXBuildFile; fileRef = 28BA89811CE7336500A98104 /* Keyboard Layouts */; };
|
||||
28BA89851CE73E7200A98104 /* TrackPad.m in Sources */ = {isa = PBXBuildFile; fileRef = 28BA89841CE73E7200A98104 /* TrackPad.m */; };
|
||||
28BA89881CE73FBC00A98104 /* MNVMApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 28BA89871CE73FBC00A98104 /* MNVMApplication.m */; };
|
||||
28BDBEA01D230EEB0072ED5B /* MYOSGLUE.m in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8ECB1CD4CDC500FE25A8 /* MYOSGLUE.m */; };
|
||||
28BDBEB11D230EEB0072ED5B /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 283423EC1CFA329C0088B634 /* Icon.png */; };
|
||||
28BDBEB21D230EEB0072ED5B /* Icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 283423ED1CFA329C0088B634 /* Icon@2x.png */; };
|
||||
|
@ -58,6 +57,11 @@
|
|||
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 */; };
|
||||
28D3C61D2B7795060079E915 /* SettingsMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D3C61C2B7795060079E915 /* SettingsMenu.swift */; };
|
||||
28D3C61F2B77B51D0079E915 /* PowerMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D3C61E2B77B51D0079E915 /* PowerMenu.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 */; };
|
||||
|
@ -272,8 +276,6 @@
|
|||
28BA89811CE7336500A98104 /* Keyboard Layouts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "Keyboard Layouts"; sourceTree = "<group>"; };
|
||||
28BA89831CE73E7200A98104 /* TrackPad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackPad.h; sourceTree = "<group>"; };
|
||||
28BA89841CE73E7200A98104 /* TrackPad.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TrackPad.m; sourceTree = "<group>"; };
|
||||
28BA89861CE73FBC00A98104 /* MNVMApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MNVMApplication.h; sourceTree = "<group>"; };
|
||||
28BA89871CE73FBC00A98104 /* MNVMApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MNVMApplication.m; sourceTree = "<group>"; };
|
||||
28BDBEB71D230EEB0072ED5B /* MacII-640x480.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = "MacII-640x480.framework"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
28C67BEE2AC49E46000C7540 /* MacII-512x384.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = "MacII-512x384.framework"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
28C67BF12AC49F0F000C7540 /* CNFUDALL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNFUDALL.h; sourceTree = "<group>"; };
|
||||
|
@ -282,6 +284,12 @@
|
|||
28CE8ECB1CD4CDC500FE25A8 /* MYOSGLUE.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYOSGLUE.m; sourceTree = "<group>"; };
|
||||
28CE8ED41CD4F56C00FE25A8 /* ScreenView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreenView.h; sourceTree = "<group>"; };
|
||||
28CE8ED51CD4F56C00FE25A8 /* ScreenView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScreenView.m; sourceTree = "<group>"; };
|
||||
28D3C6132B7681420079E915 /* Mini vMac-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Mini vMac-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
28D3C6142B7681420079E915 /* VisionSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisionSupport.swift; sourceTree = "<group>"; };
|
||||
28D3C6162B76B8970079E915 /* DefaultSceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultSceneDelegate.swift; sourceTree = "<group>"; };
|
||||
28D3C61A2B7781700079E915 /* KeyboardSceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardSceneDelegate.swift; sourceTree = "<group>"; };
|
||||
28D3C61C2B7795060079E915 /* SettingsMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsMenu.swift; sourceTree = "<group>"; };
|
||||
28D3C61E2B77B51D0079E915 /* PowerMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PowerMenu.swift; sourceTree = "<group>"; };
|
||||
28D5A3FB1CD6868E001A33F6 /* TouchScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TouchScreen.h; sourceTree = "<group>"; };
|
||||
28D5A3FC1CD6868E001A33F6 /* TouchScreen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TouchScreen.m; sourceTree = "<group>"; };
|
||||
28E3B7CC251D0F12007C273F /* MOUSEMDV.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MOUSEMDV.c; sourceTree = "<group>"; };
|
||||
|
@ -601,8 +609,6 @@
|
|||
children = (
|
||||
28F676C31CD15E0B00FC6FA6 /* AppDelegate.h */,
|
||||
28F676C41CD15E0B00FC6FA6 /* AppDelegate.m */,
|
||||
28BA89861CE73FBC00A98104 /* MNVMApplication.h */,
|
||||
28BA89871CE73FBC00A98104 /* MNVMApplication.m */,
|
||||
28CE8ED41CD4F56C00FE25A8 /* ScreenView.h */,
|
||||
28CE8ED51CD4F56C00FE25A8 /* ScreenView.m */,
|
||||
28D5A3FB1CD6868E001A33F6 /* TouchScreen.h */,
|
||||
|
@ -611,6 +617,9 @@
|
|||
28BA89841CE73E7200A98104 /* TrackPad.m */,
|
||||
28F676C61CD15E0B00FC6FA6 /* ViewController.h */,
|
||||
28F676C71CD15E0B00FC6FA6 /* ViewController.m */,
|
||||
28D3C6142B7681420079E915 /* VisionSupport.swift */,
|
||||
28D3C61C2B7795060079E915 /* SettingsMenu.swift */,
|
||||
28D3C61E2B77B51D0079E915 /* PowerMenu.swift */,
|
||||
28848B601CDE97D600B86C45 /* InsertDiskViewController.h */,
|
||||
28848B611CDE97D600B86C45 /* InsertDiskViewController.m */,
|
||||
28848B631CDE97E900B86C45 /* SettingsViewController.h */,
|
||||
|
@ -627,6 +636,8 @@
|
|||
28F6B4CE1CF77099002D76D0 /* compat.m */,
|
||||
283CA9821DF47AF300B33D5E /* BTCMouse.h */,
|
||||
283422EF1CF8F33A0088B634 /* Emulator Bundles */,
|
||||
28D3C6162B76B8970079E915 /* DefaultSceneDelegate.swift */,
|
||||
28D3C61A2B7781700079E915 /* KeyboardSceneDelegate.swift */,
|
||||
);
|
||||
path = "Mini vMac";
|
||||
sourceTree = "<group>";
|
||||
|
@ -634,6 +645,7 @@
|
|||
28F676C01CD15E0B00FC6FA6 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
28D3C6132B7681420079E915 /* Mini vMac-Bridging-Header.h */,
|
||||
28F6B4551CF07C9A002D76D0 /* libhfs */,
|
||||
28F6B4541CF07C8D002D76D0 /* libmfs */,
|
||||
28F6B4531CF07C83002D76D0 /* libres */,
|
||||
|
@ -950,6 +962,7 @@
|
|||
28F676BC1CD15E0B00FC6FA6 = {
|
||||
CreatedOnToolsVersion = 7.3;
|
||||
DevelopmentTeam = UJXNDZ5TNU;
|
||||
LastSwiftMigration = 1520;
|
||||
};
|
||||
28F6B48D1CF07DDD002D76D0 = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
|
@ -1287,14 +1300,18 @@
|
|||
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 */,
|
||||
28D3C61D2B7795060079E915 /* SettingsMenu.swift in Sources */,
|
||||
28BA897F1CE7315400A98104 /* KBKeyboardLayout.m in Sources */,
|
||||
28D3C61B2B7781700079E915 /* KeyboardSceneDelegate.swift in Sources */,
|
||||
28D3C61F2B77B51D0079E915 /* PowerMenu.swift in Sources */,
|
||||
28848B621CDE97D600B86C45 /* InsertDiskViewController.m in Sources */,
|
||||
28F676C81CD15E0B00FC6FA6 /* ViewController.m in Sources */,
|
||||
28D5A3FD1CD6868F001A33F6 /* TouchScreen.m in Sources */,
|
||||
|
@ -1405,6 +1422,7 @@
|
|||
INFOPLIST_PREPROCESS = YES;
|
||||
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -1414,6 +1432,10 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac.macplus4m;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||
USER_HEADER_SEARCH_PATHS = (
|
||||
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
|
||||
"\"$(SRCROOT)/Mini vMac/\"",
|
||||
|
@ -1440,6 +1462,7 @@
|
|||
INFOPLIST_PREPROCESS = YES;
|
||||
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -1449,6 +1472,10 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac.macplus4m;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||
USER_HEADER_SEARCH_PATHS = (
|
||||
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
|
||||
"\"$(SRCROOT)/Mini vMac/\"",
|
||||
|
@ -1475,6 +1502,7 @@
|
|||
INFOPLIST_PREPROCESS = YES;
|
||||
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -1484,6 +1512,10 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac.macii;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||
USER_HEADER_SEARCH_PATHS = (
|
||||
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
|
||||
"\"$(SRCROOT)/Mini vMac/\"",
|
||||
|
@ -1510,6 +1542,7 @@
|
|||
INFOPLIST_PREPROCESS = YES;
|
||||
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -1519,6 +1552,10 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac.macii;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||
USER_HEADER_SEARCH_PATHS = (
|
||||
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
|
||||
"\"$(SRCROOT)/Mini vMac/\"",
|
||||
|
@ -1545,6 +1582,7 @@
|
|||
INFOPLIST_PREPROCESS = YES;
|
||||
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -1554,6 +1592,10 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac.mac128k;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||
USER_HEADER_SEARCH_PATHS = (
|
||||
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
|
||||
"\"$(SRCROOT)/Mini vMac/\"",
|
||||
|
@ -1580,6 +1622,7 @@
|
|||
INFOPLIST_PREPROCESS = YES;
|
||||
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -1589,6 +1632,10 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac.mac128k;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||
USER_HEADER_SEARCH_PATHS = (
|
||||
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
|
||||
"\"$(SRCROOT)/Mini vMac/\"",
|
||||
|
@ -1615,6 +1662,7 @@
|
|||
INFOPLIST_PREPROCESS = YES;
|
||||
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -1624,6 +1672,10 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = "net.namedfork.minivmac.macii-640x480";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||
USER_HEADER_SEARCH_PATHS = (
|
||||
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
|
||||
"\"$(SRCROOT)/Mini vMac/\"",
|
||||
|
@ -1650,6 +1702,7 @@
|
|||
INFOPLIST_PREPROCESS = YES;
|
||||
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -1659,6 +1712,10 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = "net.namedfork.minivmac.macii-640x480";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||
USER_HEADER_SEARCH_PATHS = (
|
||||
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
|
||||
"\"$(SRCROOT)/Mini vMac/\"",
|
||||
|
@ -1685,15 +1742,20 @@
|
|||
INFOPLIST_PREPROCESS = YES;
|
||||
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.namedfork.minivmac.macii-640x480";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.namedfork.minivmac.macii-512x384";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||
USER_HEADER_SEARCH_PATHS = (
|
||||
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
|
||||
"\"$(SRCROOT)/Mini vMac/\"",
|
||||
|
@ -1720,15 +1782,20 @@
|
|||
INFOPLIST_PREPROCESS = YES;
|
||||
INFOPLIST_PREPROCESSOR_DEFINITIONS = PLIST_PREPROCESSOR;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.namedfork.minivmac.macii-640x480";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "net.namedfork.minivmac.macii-512x384";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||
USER_HEADER_SEARCH_PATHS = (
|
||||
"\"$(SRCROOT)/Mini vMac/$(PRODUCT_NAME)\"",
|
||||
"\"$(SRCROOT)/Mini vMac/\"",
|
||||
|
@ -1792,6 +1859,7 @@
|
|||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
|
@ -1841,6 +1909,7 @@
|
|||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
|
@ -1850,13 +1919,14 @@
|
|||
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;
|
||||
DEVELOPMENT_TEAM = UJXNDZ5TNU;
|
||||
HEADER_SEARCH_PATHS = "$(SRCROOT)";
|
||||
INFOPLIST_FILE = "Mini vMac/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
@ -1866,6 +1936,13 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "";
|
||||
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;
|
||||
};
|
||||
|
@ -1873,13 +1950,14 @@
|
|||
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;
|
||||
DEVELOPMENT_TEAM = UJXNDZ5TNU;
|
||||
HEADER_SEARCH_PATHS = "$(SRCROOT)";
|
||||
INFOPLIST_FILE = "Mini vMac/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
@ -1889,70 +1967,100 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = net.namedfork.minivmac;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "";
|
||||
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;
|
||||
};
|
||||
28F6B4951CF07DDD002D76D0 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
||||
CLANG_ENABLE_MODULES = NO;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
OTHER_CFLAGS = "-DHAVE_CONFIG_H";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "xrsimulator xros watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
28F6B4961CF07DDD002D76D0 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
||||
CLANG_ENABLE_MODULES = NO;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
OTHER_CFLAGS = "-DHAVE_CONFIG_H";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "xrsimulator xros watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
28F6B4AF1CF07EC9002D76D0 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = NO;
|
||||
HEADER_SEARCH_PATHS = "$(SRCROOT)";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
OTHER_CFLAGS = "-DUSE_LIBRES";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "xrsimulator xros watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
28F6B4B01CF07EC9002D76D0 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = NO;
|
||||
HEADER_SEARCH_PATHS = "$(SRCROOT)";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
OTHER_CFLAGS = "-DUSE_LIBRES";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "xrsimulator xros watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
28F6B4BD1CF07F32002D76D0 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "xrsimulator xros watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
28F6B4BE1CF07F32002D76D0 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "xrsimulator xros watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
7
Mini vMac.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Mini vMac.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -40,7 +40,7 @@
|
|||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Release"
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
|
|
|
@ -22,15 +22,17 @@ extern NSString *DocumentsChangedNotification;
|
|||
@property (nonatomic, readonly) NSString *emulatorBundlesPath;
|
||||
@property (readonly, nonatomic, getter = isSandboxed) BOOL sandboxed;
|
||||
@property (readonly, nonatomic) id<Emulator> sharedEmulator;
|
||||
@property (readonly, nonatomic) NSArray<NSString*> *keyboardLayoutPaths;
|
||||
|
||||
+ (instancetype)sharedInstance;
|
||||
+ (id<Emulator>)sharedEmulator;
|
||||
@property (class, readonly, strong) AppDelegate *sharedInstance NS_SWIFT_NAME(shared);
|
||||
@property (class, readonly, strong) id<Emulator> sharedEmulator NS_SWIFT_NAME(emulator);
|
||||
- (void)loadAndStartEmulator;
|
||||
|
||||
- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message;
|
||||
- (IBAction)showInsertDisk:(id)sender;
|
||||
- (IBAction)showSettings:(id)sender;
|
||||
- (IBAction)showGestureHelp:(id)sender;
|
||||
- (UIScene*)sceneWithName:(NSString*)name;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#import "AppDelegate.h"
|
||||
#import "SettingsViewController.h"
|
||||
#import "InsertDiskViewController.h"
|
||||
#import "ViewController.h"
|
||||
|
||||
static AppDelegate *sharedAppDelegate = nil;
|
||||
static NSObject<Emulator> *sharedEmulator = nil;
|
||||
|
@ -101,7 +102,14 @@ NSString *DocumentsChangedNotification = @"documentsChanged";
|
|||
NSBundle *emulatorBundle = [NSBundle bundleWithPath:emulatorBundlePath];
|
||||
[emulatorBundle load];
|
||||
sharedEmulator = [[emulatorBundle principalClass] new];
|
||||
sharedEmulator.rootViewController = self.window.rootViewController;
|
||||
sharedEmulator.showAlert = ^(NSString *title, NSString *message) {
|
||||
[self showAlertWithTitle:title message:message];
|
||||
};
|
||||
sharedEmulator.dataPath = self.documentsPath;
|
||||
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
|
||||
[ViewController adjustToScreenSize];
|
||||
#endif
|
||||
return sharedEmulator != nil;
|
||||
}
|
||||
|
||||
|
@ -167,8 +175,11 @@ NSString *DocumentsChangedNotification = @"documentsChanged";
|
|||
});
|
||||
return;
|
||||
}
|
||||
BOOL wasRunning = sharedEmulator.isRunning;
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
|
||||
[sharedEmulator setRunning:wasRunning];
|
||||
}]];
|
||||
UIViewController *controller = self.window.rootViewController;
|
||||
while (controller.presentedViewController) {
|
||||
controller = controller.presentedViewController;
|
||||
|
@ -178,7 +189,7 @@ NSString *DocumentsChangedNotification = @"documentsChanged";
|
|||
|
||||
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
|
||||
BOOL success = NO;
|
||||
if ([shortcutItem.type isEqualToString:@"disk"] && sharedEmulator.isRunning) {
|
||||
if ([shortcutItem.type isEqualToString:@"disk"]) {
|
||||
NSString *fileName = (NSString*)shortcutItem.userInfo[@"disk"];
|
||||
NSString *filePath = [self.documentsPath stringByAppendingPathComponent:fileName];
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath] && ![sharedEmulator isDiskInserted:filePath]) {
|
||||
|
@ -246,6 +257,16 @@ NSString *DocumentsChangedNotification = @"documentsChanged";
|
|||
return userKeyboardLayoutsPath;
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)keyboardLayoutPaths {
|
||||
NSArray *keyboardLayouts = [[NSBundle mainBundle] pathsForResourcesOfType:@"nfkeyboardlayout" inDirectory:@"Keyboard Layouts"];
|
||||
NSString *userKeyboardLayoutsPath = [AppDelegate sharedInstance].userKeyboardLayoutsPath;
|
||||
NSArray *userKeyboardLayouts = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:userKeyboardLayoutsPath error:nil] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"pathExtension.lowercaseString = %@", @"nfkeyboardlayout"]];
|
||||
if (userKeyboardLayouts.count > 0) {
|
||||
keyboardLayouts = [keyboardLayouts arrayByAddingObjectsFromArray:userKeyboardLayouts];
|
||||
}
|
||||
return keyboardLayouts;
|
||||
}
|
||||
|
||||
- (BOOL)importFileToDocuments:(NSURL *)url copy:(BOOL)copy {
|
||||
if (url.fileURL) {
|
||||
// opening file
|
||||
|
@ -304,4 +325,41 @@ 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 sceneWithName:@"Default"] == nil) {
|
||||
[[AppDelegate sharedEmulator] setRunning:YES];
|
||||
return [UISceneConfiguration configurationWithName:@"Default" sessionRole:UIWindowSceneSessionRoleApplication];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
|
||||
if ([self sceneWithName:@"Default"] == nil) {
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"runInBackground"] == NO) {
|
||||
[[AppDelegate sharedEmulator] setRunning:NO];
|
||||
}
|
||||
UIScene *keyboardScene = [self sceneWithName:@"Keyboard"];
|
||||
if (keyboardScene != nil) {
|
||||
// if only keyboard is left, close it too
|
||||
[application requestSceneSessionDestruction:keyboardScene.session options:nil errorHandler:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (UIScene*)sceneWithName:(NSString*)name {
|
||||
for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) {
|
||||
if ([scene.session.configuration.name isEqualToString:name]) {
|
||||
return scene;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -2,113 +2,110 @@
|
|||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "3x"
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-Small@2x.png",
|
||||
"scale" : "2x"
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-Small@3x.png",
|
||||
"scale" : "3x"
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-Small-40@2x-1.png",
|
||||
"scale" : "2x"
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-Small-40@3x.png",
|
||||
"scale" : "3x"
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-60@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-60@3x.png",
|
||||
"scale" : "3x"
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"scale" : "1x"
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-Small.png",
|
||||
"scale" : "1x"
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-Small@2x-1.png",
|
||||
"scale" : "2x"
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-Small-40.png",
|
||||
"scale" : "1x"
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-Small-40@2x.png",
|
||||
"scale" : "2x"
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-76.png",
|
||||
"scale" : "1x"
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-76@2x.png",
|
||||
"scale" : "2x"
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-iPadPro.png",
|
||||
"scale" : "2x"
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"size" : "1024x1024",
|
||||
"scale" : "1x"
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
},
|
||||
"properties" : {
|
||||
"pre-rendered" : true
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "back.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 25 KiB |
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"frame-size" : {
|
||||
"height" : 512,
|
||||
"width" : 512
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"layers" : [
|
||||
{
|
||||
"filename" : "Front.solidimagestacklayer"
|
||||
},
|
||||
{
|
||||
"filename" : "Middle.solidimagestacklayer"
|
||||
},
|
||||
{
|
||||
"filename" : "Back.solidimagestacklayer"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Icon.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 736 B |
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"frame-size" : {
|
||||
"height" : 512,
|
||||
"width" : 512
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "screen.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 934 B |
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"frame-size" : {
|
||||
"height" : 512,
|
||||
"width" : 512
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -23,6 +23,11 @@
|
|||
"filename" : "KBCapsLock~ipad@2x.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "KBCapsLock~ipad@2x 1.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBCapsLock.imageset/KBCapsLock~ipad@2x 1.png
vendored
Normal file
After Width: | Height: | Size: 317 B |
|
@ -23,6 +23,11 @@
|
|||
"filename" : "KBClearDown~ipad@2x.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "KBClearDown~ipad@2x 1.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBClearDown.imageset/KBClearDown~ipad@2x 1.png
vendored
Normal file
After Width: | Height: | Size: 401 B |
|
@ -23,6 +23,11 @@
|
|||
"filename" : "KBClearUp~ipad@2x.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "KBClearUp~ipad@2x 1.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBClearUp.imageset/KBClearUp~ipad@2x 1.png
vendored
Normal file
After Width: | Height: | Size: 563 B |
|
@ -23,6 +23,11 @@
|
|||
"filename" : "KBCommand@2x~ipad.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "KBCommand@2x~ipad 1.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBCommand.imageset/KBCommand@2x~ipad 1.png
vendored
Normal file
After Width: | Height: | Size: 1.0 KiB |
|
@ -23,6 +23,11 @@
|
|||
"filename" : "KBDeleteDown~ipad@2x.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "KBDeleteDown~ipad@2x 1.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBDeleteDown.imageset/KBDeleteDown~ipad@2x 1.png
vendored
Normal file
After Width: | Height: | Size: 526 B |
|
@ -23,6 +23,11 @@
|
|||
"filename" : "KBDeleteUp~ipad@2x.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "KBDeleteUp~ipad@2x 1.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBDeleteUp.imageset/KBDeleteUp~ipad@2x 1.png
vendored
Normal file
After Width: | Height: | Size: 726 B |
|
@ -23,6 +23,11 @@
|
|||
"filename" : "KBForwardDeleteDown~ipad@2x.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "KBForwardDeleteDown~ipad@2x 1.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBForwardDeleteDown.imageset/KBForwardDeleteDown~ipad@2x 1.png
vendored
Normal file
After Width: | Height: | Size: 526 B |
|
@ -23,6 +23,11 @@
|
|||
"filename" : "KBForwardDeleteUp~ipad@2x.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "KBForwardDeleteUp~ipad@2x 1.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBForwardDeleteUp.imageset/KBForwardDeleteUp~ipad@2x 1.png
vendored
Normal file
After Width: | Height: | Size: 718 B |
|
@ -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" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBHide.imageset/KBHide~ipad 2.png
vendored
Normal file
After Width: | Height: | Size: 242 B |
BIN
Mini vMac/Assets.xcassets/KBHide.imageset/KBHide~ipad@2x 1.png
vendored
Normal file
After Width: | Height: | Size: 438 B |
|
@ -219,6 +219,25 @@
|
|||
"mode" : "9-part"
|
||||
},
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "KBKey@2x~ipad-2 1.png",
|
||||
"idiom" : "vision",
|
||||
"resizing" : {
|
||||
"cap-insets" : {
|
||||
"bottom" : 32,
|
||||
"left" : 32,
|
||||
"right" : 32,
|
||||
"top" : 32
|
||||
},
|
||||
"center" : {
|
||||
"height" : 2,
|
||||
"mode" : "tile",
|
||||
"width" : 2
|
||||
},
|
||||
"mode" : "9-part"
|
||||
},
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBKey.imageset/KBKey@2x~ipad-2 1.png
vendored
Normal file
After Width: | Height: | Size: 634 B |
|
@ -219,6 +219,25 @@
|
|||
"mode" : "9-part"
|
||||
},
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "KBKeyDark@2x~ipad-1 1.png",
|
||||
"idiom" : "vision",
|
||||
"resizing" : {
|
||||
"cap-insets" : {
|
||||
"bottom" : 32,
|
||||
"left" : 32,
|
||||
"right" : 32,
|
||||
"top" : 32
|
||||
},
|
||||
"center" : {
|
||||
"height" : 2,
|
||||
"mode" : "tile",
|
||||
"width" : 2
|
||||
},
|
||||
"mode" : "9-part"
|
||||
},
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBKeyDark.imageset/KBKeyDark@2x~ipad-1 1.png
vendored
Normal file
After Width: | Height: | Size: 636 B |
|
@ -23,6 +23,11 @@
|
|||
"filename" : "KBNumPad@2x~ipad.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "KBNumPad@2x~ipad 1.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBNumPad.imageset/KBNumPad@2x~ipad 1.png
vendored
Normal file
After Width: | Height: | Size: 178 B |
|
@ -23,6 +23,11 @@
|
|||
"filename" : "KBOption@2x~ipad.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "KBOption@2x~ipad 1.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBOption.imageset/KBOption@2x~ipad 1.png
vendored
Normal file
After Width: | Height: | Size: 365 B |
|
@ -23,6 +23,11 @@
|
|||
"filename" : "KBShiftDown~ipad@2x.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "KBShiftDown~ipad@2x 1.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBShiftDown.imageset/KBShiftDown~ipad@2x 1.png
vendored
Normal file
After Width: | Height: | Size: 274 B |
|
@ -23,6 +23,11 @@
|
|||
"filename" : "KBShiftUp~ipad@2x.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "KBShiftUp~ipad@2x 1.png",
|
||||
"idiom" : "vision",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
|
BIN
Mini vMac/Assets.xcassets/KBShiftUp.imageset/KBShiftUp~ipad@2x 1.png
vendored
Normal file
After Width: | Height: | Size: 467 B |
|
@ -1,23 +1,26 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "reset.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "reset@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "reset@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
|
@ -1,23 +1,26 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Settings.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Settings@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Settings@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
64
Mini vMac/DefaultSceneDelegate.swift
Normal file
|
@ -0,0 +1,64 @@
|
|||
//
|
||||
// DefaultSceneDelegate.swift
|
||||
// Mini vMac
|
||||
//
|
||||
// Created by Jesús A. Álvarez on 2024-02-09.
|
||||
// Copyright © 2024 namedfork. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class DefaultSceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
var window: UIWindow? // keep window reference to be able to set background colour before destroying
|
||||
|
||||
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 appDelegate = AppDelegate.shared else {
|
||||
fatalError("No app delegate")
|
||||
}
|
||||
|
||||
let size = CGSize(width: 1024.0, height: 684.0)
|
||||
windowScene.sizeRestrictions?.minimumSize = size
|
||||
windowScene.sizeRestrictions?.maximumSize = size
|
||||
|
||||
window = UIWindow(windowScene: windowScene)
|
||||
if let window {
|
||||
appDelegate.window = window
|
||||
window.rootViewController = UIStoryboard(name: "Main", bundle: .main).instantiateInitialViewController()
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
self.destroyOtherSessions(not: session)
|
||||
}
|
||||
|
||||
private func destroyOtherSessions(not session: UISceneSession) {
|
||||
let app = UIApplication.shared
|
||||
let options = UIWindowSceneDestructionRequestOptions()
|
||||
options.windowDismissalAnimation = .decline
|
||||
for otherSession in app.openSessions.filter({ $0 != session && $0.configuration.name == "Default"}) {
|
||||
if let window = (otherSession.scene as? UIWindowScene)?.windows.first {
|
||||
window.rootViewController?.view.removeFromSuperview()
|
||||
window.backgroundColor = .darkGray
|
||||
app.requestSceneSessionRefresh(otherSession)
|
||||
}
|
||||
app.requestSceneSessionDestruction(otherSession, options: options)
|
||||
// window will remain visible until window switcher is dismissed!
|
||||
}
|
||||
}
|
||||
|
||||
func sceneDidEnterBackground(_ scene: UIScene) {
|
||||
let app = UIApplication.shared
|
||||
if UserDefaults.standard.bool(forKey: "runInBackground") == false && app.connectedScenes.filter({ $0 != scene && $0.session.configuration.name == "Default"}).isEmpty {
|
||||
AppDelegate.emulator.isRunning = false
|
||||
}
|
||||
}
|
||||
|
||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
||||
AppDelegate.emulator.isRunning = true
|
||||
}
|
||||
|
||||
func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
|
||||
AppDelegate.shared.application(UIApplication.shared, performActionFor: shortcutItem, completionHandler: completionHandler)
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
@import CoreGraphics;
|
||||
@import QuartzCore;
|
||||
|
||||
typedef enum : NSInteger {
|
||||
typedef NS_ENUM(NSInteger, EmulatorSpeed) {
|
||||
EmulatorSpeedAllOut = -1,
|
||||
EmulatorSpeed1x = 0,
|
||||
EmulatorSpeed2x = 1,
|
||||
|
@ -18,7 +18,7 @@ typedef enum : NSInteger {
|
|||
EmulatorSpeed8x = 3,
|
||||
EmulatorSpeed16x = 4,
|
||||
EmulatorSpeed32x = 5
|
||||
} EmulatorSpeed;
|
||||
};
|
||||
|
||||
@protocol Emulator <NSObject>
|
||||
|
||||
|
@ -38,6 +38,9 @@ typedef enum : NSInteger {
|
|||
@property (nonatomic, readonly) BOOL anyDiskInserted;
|
||||
@property (nonatomic, readonly) NSString *currentApplication;
|
||||
|
||||
@property (nonatomic, strong) void (^showAlert)(NSString *title, NSString *message);
|
||||
@property (nonatomic, strong) UIViewController *rootViewController;
|
||||
|
||||
- (void)run;
|
||||
- (void)reset;
|
||||
- (void)interrupt;
|
||||
|
|
|
@ -176,5 +176,28 @@
|
|||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<true/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>Default</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).DefaultSceneDelegate</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>Keyboard</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).KeyboardSceneDelegate</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -473,7 +473,7 @@
|
|||
}
|
||||
|
||||
- (void)showFileActivityIndicatorWithTitle:(NSString*)title completion:(void (^_Nonnull)(UIActivityIndicatorView* activityIndicatorView))completionBlock {
|
||||
UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
|
||||
UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge];
|
||||
if (@available(iOS 13, *)) {
|
||||
activityIndicatorView.color = [UIColor labelColor];
|
||||
} else {
|
||||
|
|
|
@ -9,6 +9,12 @@
|
|||
#import <UIKit/UIKit.h>
|
||||
#import "KBKeyboardLayout.h"
|
||||
|
||||
#define KC_COMMAND 55
|
||||
#define KC_SHIFT 56
|
||||
#define KC_CAPSLOCK 57
|
||||
#define KC_OPTION 58
|
||||
#define KC_CONTROL 59
|
||||
|
||||
@class KBKey;
|
||||
|
||||
@protocol KBKeyboardViewDelegate <NSObject>
|
||||
|
@ -22,6 +28,7 @@
|
|||
|
||||
@property (weak, nonatomic, nullable) id<KBKeyboardViewDelegate> delegate;
|
||||
@property (nonatomic, strong, nullable) KBKeyboardLayout *layout;
|
||||
@property (nonatomic, strong, nullable) UIMenu *layoutMenu;
|
||||
|
||||
@property (nonatomic, readonly, nonnull) NSArray<KBKey*>* keys;
|
||||
@property (nonatomic, readonly, nonnull) NSArray<KBKey*>* stickyKeys;
|
||||
|
|
|
@ -9,26 +9,23 @@
|
|||
#import "KBKeyboardView.h"
|
||||
#import "KBKey.h"
|
||||
|
||||
#define KC_COMMAND 55
|
||||
#define KC_SHIFT 56
|
||||
#define KC_CAPSLOCK 57
|
||||
#define KC_OPTION 58
|
||||
#define KC_CONTROL 59
|
||||
|
||||
@implementation KBKeyboardView {
|
||||
NSMutableArray *keyPlanes;
|
||||
NSMutableArray *keyPlanes, *emptyKeyPlanes;
|
||||
NSMutableSet *modifiers;
|
||||
NSMutableIndexSet *keysDown;
|
||||
CGAffineTransform defaultKeyTransform;
|
||||
CGFloat fontSize;
|
||||
CGSize selectedSize;
|
||||
UIEdgeInsets safeAreaInsets;
|
||||
CGSize intrinsicSize;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame safeAreaInsets:(UIEdgeInsets)insets {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
safeAreaInsets = insets;
|
||||
intrinsicSize = frame.size;
|
||||
#if !defined(TARGET_OS_VISION) || TARGET_OS_VISION == 0
|
||||
if (@available(iOS 13.0, *)) {
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
UIVisualEffectView *backgroundView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleSystemThickMaterial]];
|
||||
|
@ -37,8 +34,10 @@
|
|||
} else {
|
||||
self.backgroundColor = [UIColor colorWithRed:0xEB / 255.0 green:0xF0 / 255.0 blue:0xF7 / 255.0 alpha:0.9];
|
||||
}
|
||||
#endif
|
||||
modifiers = [NSMutableSet setWithCapacity:4];
|
||||
keysDown = [NSMutableIndexSet indexSet];
|
||||
self.autoresizesSubviews = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -47,10 +46,29 @@
|
|||
return [self initWithFrame:frame safeAreaInsets:UIEdgeInsetsZero];
|
||||
}
|
||||
|
||||
- (CGSize)intrinsicContentSize {
|
||||
return intrinsicSize;
|
||||
}
|
||||
|
||||
- (BOOL)isCompactKeyboardSize:(CGSize)size {
|
||||
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 selectedSize = CGSizeZero;
|
||||
for (NSValue *key in sizes) {
|
||||
|
@ -116,6 +134,7 @@
|
|||
for (int i = 0; i < numberOfKeyPlanes; i++) {
|
||||
[keyPlanes addObject:[NSNull null]];
|
||||
}
|
||||
emptyKeyPlanes = keyPlanes.mutableCopy;
|
||||
|
||||
[self switchToKeyPlane:0];
|
||||
}
|
||||
|
@ -127,7 +146,16 @@
|
|||
}
|
||||
if (scancode == VKC_HIDE) {
|
||||
key = [[KBHideKey alloc] initWithFrame:keyFrame];
|
||||
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
|
||||
if (self.layoutMenu != nil) {
|
||||
key.showsMenuAsPrimaryAction = YES;
|
||||
key.menu = self.layoutMenu;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
[key addTarget:self action:@selector(hideKeyboard:) forControlEvents:UIControlEventTouchUpInside];
|
||||
#endif
|
||||
} else if (scancode == VKC_SHIFT_CAPS) {
|
||||
key = [[KBShiftCapsKey alloc] initWithFrame:keyFrame];
|
||||
key.scancode = KC_SHIFT;
|
||||
|
|
51
Mini vMac/KeyboardSceneDelegate.swift
Normal file
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// KeyboardSceneDelegate.swift
|
||||
// Mini vMac
|
||||
//
|
||||
// Created by Jesús A. Álvarez on 2024-02-10.
|
||||
// Copyright © 2024 namedfork. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
#if os(visionOS)
|
||||
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.shared.window.rootViewController as? ViewController else {
|
||||
fatalError("No main view controller")
|
||||
}
|
||||
|
||||
scene.activationConditions.canActivateForTargetContentIdentifierPredicate = NSPredicate(format: "self == 'net.namedfork.keyboard'", argumentArray: nil)
|
||||
let defaultSize = mainViewController.keyboardViewController.preferredContentSize
|
||||
let minSize = defaultSize.applying(.init(scaleX: 0.75, y: 0.75))
|
||||
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)
|
||||
|
||||
// destroy existing keyboard window
|
||||
if let oldWindow = mainViewController.keyboardViewController?.view?.window {
|
||||
oldWindow.rootViewController = nil
|
||||
if let oldScene = oldWindow.windowScene?.session.scene {
|
||||
UIApplication.shared.requestSceneSessionDestruction(oldScene.session, options: nil)
|
||||
}
|
||||
}
|
||||
|
||||
if let window {
|
||||
window.rootViewController = mainViewController.keyboardViewController
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,13 +0,0 @@
|
|||
//
|
||||
// MNVMApplication.h
|
||||
// Mini vMac
|
||||
//
|
||||
// Created by Jesús A. Álvarez on 14/05/2016.
|
||||
// Copyright © 2016-2018 namedfork. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface MNVMApplication : UIApplication
|
||||
|
||||
@end
|
|
@ -1,120 +0,0 @@
|
|||
//
|
||||
// MNVMApplication.m
|
||||
// Mini vMac
|
||||
//
|
||||
// Created by Jesús A. Álvarez on 14/05/2016.
|
||||
// Copyright © 2016-2018 namedfork. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MNVMApplication.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@interface UIApplication ()
|
||||
- (void)handleKeyUIEvent:(UIEvent *)event;
|
||||
@end
|
||||
|
||||
Class keyboardEventClass = nil;
|
||||
|
||||
static int8_t usb_to_adb_scancode[] = {
|
||||
-1, -1, -1, -1, 0, 11, 8, 2, 14, 3, 5, 4, 34, 38, 40, 37,
|
||||
46, 45, 31, 35, 12, 15, 1, 17, 32, 9, 13, 7, 16, 6, 18, 19,
|
||||
20, 21, 23, 22, 26, 28, 25, 29, 36, 53, 51, 48, 49, 27, 24, 33,
|
||||
30, 42, 42, 41, 39, 10, 43, 47, 44, 57, 122, 120, 99, 118, 96, 97,
|
||||
98, 100, 101, 109, 103, 111, 105, 107, 113, 114, 115, 116, 117, 119, 121, 60,
|
||||
59, 61, 62, 71, 75, 67, 78, 69, 76, 83, 84, 85, 86, 87, 88, 89,
|
||||
91, 92, 82, 65, 50, 55, 126, 81, 105, 107, 113, 106, 64, 79, 80, 90,
|
||||
-1, -1, -1, -1, -1, 114, -1, -1, -1, -1, -1, -1, -1, -1, -1, 74,
|
||||
72, 73, -1, -1, -1, 95, -1, 94, -1, 93, -1, -1, -1, -1, -1, -1,
|
||||
104, 102, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
54, 56, 58, 55, 54, 56, 58, 55, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
|
||||
};
|
||||
|
||||
@interface UIPhysicalKeyboardEvent : UIPressesEvent
|
||||
|
||||
@property (nonatomic, readonly) BOOL _isKeyDown;
|
||||
@property (nonatomic, readonly) long _keyCode;
|
||||
@property (nonatomic) int _modifierFlags;
|
||||
@property(retain, nonatomic) NSString *_unmodifiedInput;
|
||||
@property(retain, nonatomic) NSString *_modifiedInput;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MNVMApplication
|
||||
{
|
||||
BOOL physicalCapsLocked;
|
||||
}
|
||||
|
||||
+ (void)load {
|
||||
// class is not visible
|
||||
keyboardEventClass = NSClassFromString(@"UIPhysicalKeyboardEvent");
|
||||
}
|
||||
|
||||
- (void)handleKeyboardEvent:(UIPhysicalKeyboardEvent *)event {
|
||||
long keycode = event._keyCode;
|
||||
int scancode = -1;
|
||||
|
||||
if (keycode >= 0 && keycode < sizeof(usb_to_adb_scancode)) {
|
||||
scancode = usb_to_adb_scancode[keycode];
|
||||
}
|
||||
|
||||
if (scancode == 57) {
|
||||
// caps lock
|
||||
if (event._isKeyDown && !physicalCapsLocked) {
|
||||
[[AppDelegate sharedEmulator] keyDown:scancode];
|
||||
physicalCapsLocked = YES;
|
||||
} else if (event._isKeyDown && physicalCapsLocked) {
|
||||
[[AppDelegate sharedEmulator] keyUp:scancode];
|
||||
physicalCapsLocked = NO;
|
||||
}
|
||||
} else if (scancode >= 0 && [AppDelegate sharedEmulator].running) {
|
||||
if (event._isKeyDown) {
|
||||
[self _updateCapsLockStatus:event];
|
||||
[[AppDelegate sharedEmulator] keyDown:scancode];
|
||||
} else {
|
||||
[[AppDelegate sharedEmulator] keyUp:scancode];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_updateCapsLockStatus:(UIPhysicalKeyboardEvent *)event {
|
||||
if (event._modifierFlags == 0 && event._unmodifiedInput.length == 1 && event._modifiedInput.length == 1) {
|
||||
unichar unmodifiedChar = [event._unmodifiedInput characterAtIndex:0];
|
||||
unichar modifiedChar = [event._modifiedInput characterAtIndex:0];
|
||||
if ([[NSCharacterSet lowercaseLetterCharacterSet] characterIsMember:unmodifiedChar]) {
|
||||
BOOL currentCapsLock = [[NSCharacterSet uppercaseLetterCharacterSet] characterIsMember:modifiedChar];
|
||||
if (currentCapsLock != physicalCapsLocked) {
|
||||
physicalCapsLocked = currentCapsLock;
|
||||
if (physicalCapsLocked) {
|
||||
[[AppDelegate sharedEmulator] keyDown:57];
|
||||
} else {
|
||||
[[AppDelegate sharedEmulator] keyUp:57];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleKeyUIEvent:(UIEvent *)event {
|
||||
static dispatch_once_t onceToken;
|
||||
static BOOL handleKeyboardEvents = YES;
|
||||
dispatch_once(&onceToken, ^{
|
||||
if ([NSProcessInfo instancesRespondToSelector:@selector(operatingSystemVersion)]) {
|
||||
handleKeyboardEvents = [NSProcessInfo processInfo].operatingSystemVersion.majorVersion >= 9;
|
||||
} else {
|
||||
handleKeyboardEvents = NO;
|
||||
}
|
||||
});
|
||||
BOOL emulatorIsFrontmost = [AppDelegate sharedEmulator].running && [AppDelegate sharedInstance].window.rootViewController.presentedViewController == nil;
|
||||
if ([event isKindOfClass:keyboardEventClass] && handleKeyboardEvents && emulatorIsFrontmost) {
|
||||
[self handleKeyboardEvent:(UIPhysicalKeyboardEvent*)event];
|
||||
} else {
|
||||
[super handleKeyUIEvent:event];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -1471,13 +1471,8 @@ LOCALPROC MacMsgDisplayOn() {
|
|||
if (SavedBriefMsg != nullpr) {
|
||||
NSString *title = NSStringCreateFromSubstCStr(SavedBriefMsg, falseblnr);
|
||||
NSString *message = NSStringCreateFromSubstCStr(SavedLongMsg, falseblnr);
|
||||
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
|
||||
blnr wasStopped = SpeedStopped;
|
||||
[alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
|
||||
SpeedStopped = wasStopped;
|
||||
}]];
|
||||
sharedEmulator.showAlert(title, message);
|
||||
SpeedStopped = trueblnr;
|
||||
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
|
||||
SavedBriefMsg = nullpr;
|
||||
SavedLongMsg = nullpr;
|
||||
}
|
||||
|
@ -1642,6 +1637,8 @@ GLOBALPROC WaitForNextTick(void) {
|
|||
}
|
||||
|
||||
@synthesize dataPath;
|
||||
@synthesize showAlert;
|
||||
@synthesize rootViewController;
|
||||
|
||||
- (instancetype)init {
|
||||
if ((self = [super init])) {
|
||||
|
@ -1792,7 +1789,7 @@ GLOBALPROC WaitForNextTick(void) {
|
|||
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Save", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
|
||||
[self didMakeNewDisk:self->nameTextField.text size:size];
|
||||
}]];
|
||||
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
|
||||
[sharedEmulator.rootViewController presentViewController:alertController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (void)didMakeNewDisk:(NSString*)fileName size:(NSInteger)size {
|
||||
|
|
9
Mini vMac/Mini vMac-Bridging-Header.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
//
|
||||
// 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 "EmulatorProtocol.h"
|
||||
#import "KBKeyboardView.h"
|
||||
#import "KBKeyboardLayout.h"
|
35
Mini vMac/PowerMenu.swift
Normal file
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// PowerMenu.swift
|
||||
// Mini vMac
|
||||
//
|
||||
// Created by Jesús A. Álvarez on 2024-02-10.
|
||||
// Copyright © 2024 namedfork. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
#if os(visionOS)
|
||||
struct PowerMenu: View {
|
||||
var body: some View {
|
||||
Menu() {
|
||||
Section("Power") {
|
||||
Button("Restart", systemImage: "arrowtriangle.right", role: .destructive) {
|
||||
AppDelegate.shared.loadAndStartEmulator()
|
||||
}
|
||||
Button("Interrupt", systemImage: "arrowtriangle.down.circle", role: .destructive) {
|
||||
AppDelegate.emulator.interrupt()
|
||||
}
|
||||
Button("Shut Down", systemImage: "minus.circle", role: .destructive) {
|
||||
exit(0)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "power")
|
||||
}.menuOrder(.fixed)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
PowerMenu()
|
||||
}
|
||||
#endif
|
|
@ -29,7 +29,7 @@ static ScreenView *sharedScreenView = nil;
|
|||
[self updateVideoLayer];
|
||||
[self.layer addSublayer:videoLayer];
|
||||
[[AppDelegate sharedInstance] addObserver:self forKeyPath:@"sharedEmulator" options:NSKeyValueObservingOptionNew context:NULL];
|
||||
[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"screenFilter" options:NSKeyValueObservingOptionNew context:NULL];
|
||||
[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"screenFilter" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
|
||||
}
|
||||
|
||||
+ (instancetype)sharedScreenView {
|
||||
|
@ -57,17 +57,25 @@ static ScreenView *sharedScreenView = nil;
|
|||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
CGRect viewBounds = self.bounds;
|
||||
CGFloat screenScale = MAX(screenSize.width / viewBounds.size.width, screenSize.height / viewBounds.size.height);
|
||||
if (screenScale > 0.9 && screenScale <= 1.0) {
|
||||
CGFloat screenScale = MIN(viewBounds.size.width / screenSize.width, viewBounds.size.height / screenSize.height);
|
||||
NSString *screenFilter = [[NSUserDefaults standardUserDefaults] stringForKey:@"screenFilter"];
|
||||
if ([screenFilter isEqualToString:kCAFilterNearest] && screenScale > 1.0) {
|
||||
screenScale = floor(screenScale);
|
||||
} else if (screenScale > 1.0 && screenScale <= 1.1) {
|
||||
screenScale = 1.0;
|
||||
}
|
||||
screenBounds = CGRectMake(0, 0, screenSize.width / screenScale, screenSize.height / screenScale);
|
||||
screenBounds = CGRectMake(0, 0, screenSize.width * screenScale, screenSize.height * screenScale);
|
||||
screenBounds.origin.x = (viewBounds.size.width - screenBounds.size.width)/2;
|
||||
screenBounds = CGRectIntegral(screenBounds);
|
||||
|
||||
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && (viewBounds.size.height - screenBounds.size.height) >= 30.0) {
|
||||
// move under multitasking indicator on iPad
|
||||
screenBounds.origin.y += 30;
|
||||
}
|
||||
videoLayer.frame = screenBounds;
|
||||
screenBounds.origin.y = self.frame.origin.y;
|
||||
screenBounds.origin.y += self.frame.origin.y;
|
||||
BOOL scaleIsIntegral = (floor(screenScale) == screenScale);
|
||||
NSString *screenFilter = scaleIsIntegral ? kCAFilterNearest : [[NSUserDefaults standardUserDefaults] stringForKey:@"screenFilter"];
|
||||
if (scaleIsIntegral) screenFilter = kCAFilterNearest;
|
||||
videoLayer.magnificationFilter = screenFilter;
|
||||
videoLayer.minificationFilter = screenFilter;
|
||||
}
|
||||
|
@ -75,13 +83,19 @@ static ScreenView *sharedScreenView = nil;
|
|||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
|
||||
if ([object isEqual:[NSUserDefaults standardUserDefaults]]) {
|
||||
if ([keyPath isEqualToString:@"screenFilter"]) {
|
||||
NSString *oldValue = change[NSKeyValueChangeOldKey];
|
||||
NSString *value = change[NSKeyValueChangeNewKey];
|
||||
videoLayer.magnificationFilter = value;
|
||||
videoLayer.minificationFilter = value;
|
||||
if ([value isEqualToString:kCAFilterNearest] || [oldValue isEqualToString:kCAFilterNearest]) {
|
||||
[self setNeedsLayout];
|
||||
[self layoutIfNeeded];
|
||||
}
|
||||
}
|
||||
} else if (object == [AppDelegate sharedInstance] && [keyPath isEqualToString:@"sharedEmulator"]) {
|
||||
[self updateVideoLayer];
|
||||
[self layoutSubviews];
|
||||
[self setNeedsLayout];
|
||||
[self layoutIfNeeded];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
141
Mini vMac/SettingsMenu.swift
Normal file
|
@ -0,0 +1,141 @@
|
|||
//
|
||||
// SettingsMenu.swift
|
||||
// Mini vMac
|
||||
//
|
||||
// Created by Jesús A. Álvarez on 2024-02-10.
|
||||
// Copyright © 2024 namedfork. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
#if os(visionOS)
|
||||
struct SettingsMenu: View {
|
||||
var body: some View {
|
||||
Menu() {
|
||||
Section("Settings") {
|
||||
SpeedMenu()
|
||||
MachineMenu()
|
||||
DisplayScalingMenu()
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "gear")
|
||||
}.menuOrder(.fixed)
|
||||
}
|
||||
}
|
||||
|
||||
struct SpeedMenu: View {
|
||||
@AppStorage("speedValue") var currentSpeed: EmulatorSpeed = .speed1x
|
||||
@AppStorage("runInBackground") var runInBackground: Bool = false
|
||||
private var currentSpeedImage: String {
|
||||
switch currentSpeed {
|
||||
case .speed1x:
|
||||
"tortoise"
|
||||
case .speedAllOut:
|
||||
"hare"
|
||||
case .speed2x:
|
||||
"2.square"
|
||||
case .speed4x:
|
||||
"4.square"
|
||||
case .speed8x:
|
||||
"8.square"
|
||||
case .speed16x:
|
||||
"16.square"
|
||||
case .speed32x:
|
||||
"32.square"
|
||||
@unknown default:
|
||||
"hare"
|
||||
}
|
||||
}
|
||||
var body: some View {
|
||||
Menu("Speed", systemImage:currentSpeedImage) {
|
||||
SpeedButton(label: "1x", speed: .speed1x)
|
||||
SpeedButton(label: "2x", speed: .speed2x)
|
||||
SpeedButton(label: "4x", speed: .speed4x)
|
||||
SpeedButton(label: "8x", speed: .speed8x)
|
||||
SpeedButton(label: "16x", speed: .speed16x)
|
||||
SpeedButton(label: "32x", speed: .speed32x)
|
||||
SpeedButton(label: "Unlimited", speed: .speedAllOut)
|
||||
Divider()
|
||||
Toggle("Run in Background", isOn: $runInBackground)
|
||||
}.menuOrder(.fixed)
|
||||
}
|
||||
}
|
||||
|
||||
struct SpeedButton: View {
|
||||
@AppStorage("speedValue") var currentSpeed: EmulatorSpeed = .speed1x
|
||||
let label: LocalizedStringKey
|
||||
let speed: EmulatorSpeed
|
||||
var body: some View {
|
||||
Toggle(label, isOn: Binding(get: {
|
||||
currentSpeed == speed
|
||||
}, set: { enable in
|
||||
if enable {
|
||||
currentSpeed = speed
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
struct MachineMenu: View {
|
||||
@AppStorage("machine") var currentMachine: String = "Plus4M"
|
||||
let bundles = AppDelegate.shared.emulatorBundles?.sorted(by: { $0.bundleIdentifier! < $1.bundleIdentifier! }) ?? []
|
||||
var body: some View {
|
||||
Menu("Machine", systemImage: "desktopcomputer") {
|
||||
ForEach(bundles, id: \.bundleIdentifier) { bundle in
|
||||
MachineButton(bundle: bundle)
|
||||
}
|
||||
}.menuOrder(.fixed)
|
||||
}
|
||||
}
|
||||
|
||||
struct MachineButton: View {
|
||||
@AppStorage("machine") var currentMachine: String = "Plus4M"
|
||||
var bundle: Bundle
|
||||
var body: some View {
|
||||
Toggle(isOn: Binding(get: {
|
||||
currentMachine == bundle.name
|
||||
}, set: { enable in
|
||||
if enable && !AppDelegate.emulator.anyDiskInserted {
|
||||
currentMachine = bundle.name
|
||||
AppDelegate.shared.loadAndStartEmulator()
|
||||
}
|
||||
}), label: {
|
||||
Text("\(bundle.displayName ?? bundle.name)\n\(bundle.getInfoString ?? "")")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate extension Bundle {
|
||||
var name: String { ((self.bundlePath as NSString).lastPathComponent as NSString).deletingPathExtension }
|
||||
var displayName: String? { self.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String }
|
||||
var getInfoString: String? { self.object(forInfoDictionaryKey: "CFBundleGetInfoString") as? String }
|
||||
}
|
||||
|
||||
struct DisplayScalingMenu: View {
|
||||
@AppStorage("screenFilter") var scalingFilter: CALayerContentsFilter = .nearest
|
||||
static let filters = [
|
||||
DisplayScalingFilter(filter: .nearest, name: "Nearest"),
|
||||
DisplayScalingFilter(filter: .linear, name: "Linear"),
|
||||
DisplayScalingFilter(filter: .trilinear, name: "Trilinear"),
|
||||
]
|
||||
var body: some View {
|
||||
Menu("Display Scaling", systemImage: "rectangle.and.text.magnifyingglass") {
|
||||
ForEach(DisplayScalingMenu.filters, id: \.filter) { filter in
|
||||
Toggle(filter.name, isOn: Binding(get: {
|
||||
scalingFilter == filter.filter
|
||||
}, set: { enable in
|
||||
if enable {
|
||||
scalingFilter = filter.filter
|
||||
}
|
||||
}))
|
||||
}
|
||||
}.menuOrder(.fixed)
|
||||
}
|
||||
}
|
||||
|
||||
struct DisplayScalingFilter {
|
||||
let filter: CALayerContentsFilter
|
||||
let name: String
|
||||
}
|
||||
|
||||
#endif
|
|
@ -37,12 +37,7 @@ typedef enum : NSInteger {
|
|||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
keyboardLayouts = [[NSBundle mainBundle] pathsForResourcesOfType:@"nfkeyboardlayout" inDirectory:@"Keyboard Layouts"];
|
||||
NSString *userKeyboardLayoutsPath = [AppDelegate sharedInstance].userKeyboardLayoutsPath;
|
||||
NSArray *userKeyboardLayouts = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:userKeyboardLayoutsPath error:nil] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"pathExtension.lowercaseString = %@", @"nfkeyboardlayout"]];
|
||||
if (userKeyboardLayouts.count > 0) {
|
||||
keyboardLayouts = [keyboardLayouts arrayByAddingObjectsFromArray:userKeyboardLayouts];
|
||||
}
|
||||
keyboardLayouts = [AppDelegate sharedInstance].keyboardLayoutPaths;
|
||||
[self loadEmulatorBundles];
|
||||
[self loadCredits];
|
||||
}
|
||||
|
@ -177,7 +172,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;
|
||||
}
|
||||
|
@ -372,7 +371,7 @@ typedef enum : NSInteger {
|
|||
// links in about
|
||||
NSString *linkURL = aboutItems[indexPath.row][@"link"];
|
||||
if (linkURL != nil) {
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:linkURL]];
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:linkURL] options:@{} completionHandler:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,13 +46,8 @@
|
|||
}
|
||||
|
||||
- (BOOL)isMouseEvent:(UIEvent *)event {
|
||||
#if __IPHONE_13_4
|
||||
if (@available(iOS 13.4, *)) {
|
||||
return event.buttonMask != 0;
|
||||
}
|
||||
#endif
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
||||
if ([self isMouseEvent:event]) {
|
||||
|
|
|
@ -18,6 +18,15 @@
|
|||
|
||||
- (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;
|
||||
- (UIMenu*)keyboardLayoutMenu;
|
||||
@end
|
||||
#endif
|
||||
|
|
|
@ -13,36 +13,80 @@
|
|||
#import "KBKeyboardView.h"
|
||||
#import "KBKeyboardLayout.h"
|
||||
|
||||
@interface ViewController () <UIAdaptivePresentationControllerDelegate>
|
||||
@interface ViewController () <UIAdaptivePresentationControllerDelegate, UIPointerInteractionDelegate>
|
||||
|
||||
@end
|
||||
|
||||
#ifdef __IPHONE_13_4
|
||||
API_AVAILABLE(ios(13.4))
|
||||
@interface ViewController (PointerInteraction) <UIPointerInteractionDelegate>
|
||||
|
||||
@end
|
||||
#endif
|
||||
static int8_t usb_to_adb_scancode[] = {
|
||||
-1, -1, -1, -1, 0, 11, 8, 2, 14, 3, 5, 4, 34, 38, 40, 37,
|
||||
46, 45, 31, 35, 12, 15, 1, 17, 32, 9, 13, 7, 16, 6, 18, 19,
|
||||
20, 21, 23, 22, 26, 28, 25, 29, 36, 53, 51, 48, 49, 27, 24, 33,
|
||||
30, 42, 42, 41, 39, 10, 43, 47, 44, 57, 122, 120, 99, 118, 96, 97,
|
||||
98, 100, 101, 109, 103, 111, 105, 107, 113, 114, 115, 116, 117, 119, 121, 60,
|
||||
59, 61, 62, 71, 75, 67, 78, 69, 76, 83, 84, 85, 86, 87, 88, 89,
|
||||
91, 92, 82, 65, 50, 55, 126, 81, 105, 107, 113, 106, 64, 79, 80, 90,
|
||||
-1, -1, -1, -1, -1, 114, -1, -1, -1, -1, -1, -1, -1, -1, -1, 74,
|
||||
72, 73, -1, -1, -1, 95, -1, 94, -1, 93, -1, -1, -1, -1, -1, -1,
|
||||
104, 102, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
54, 56, 58, 55, 54, 56, 58, 55, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
|
||||
};
|
||||
|
||||
@implementation ViewController
|
||||
{
|
||||
KBKeyboardView *keyboardView;
|
||||
UISwipeGestureRecognizer *showKeyboardGesture, *hideKeyboardGesture, *insertDiskGesture, *showSettingsGesture;
|
||||
UIControl *pointingDeviceView;
|
||||
id interaction;
|
||||
}
|
||||
|
||||
- (Point)mouseLocForCGPoint:(CGPoint)point {
|
||||
Point mouseLoc;
|
||||
CGRect screenBounds = self.screenView.screenBounds;
|
||||
CGSize screenSize = self.screenView.screenSize;
|
||||
mouseLoc.h = (point.x - screenBounds.origin.x) * (screenSize.width/screenBounds.size.width);
|
||||
mouseLoc.v = (point.y - screenBounds.origin.y) * (screenSize.height/screenBounds.size.height);
|
||||
return mouseLoc;
|
||||
UIViewController *_keyboardViewController;
|
||||
BOOL physicalCapsLocked;
|
||||
UIPointerInteraction *pointerInteraction;
|
||||
}
|
||||
|
||||
- (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.layoutMenu = [self keyboardLayoutMenu];
|
||||
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;
|
||||
|
@ -54,9 +98,6 @@ API_AVAILABLE(ios(13.4))
|
|||
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 {
|
||||
|
@ -75,6 +116,11 @@ API_AVAILABLE(ios(13.4))
|
|||
[self dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
}
|
||||
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
|
||||
if ([segue.identifier isEqualToString:@"disk"]) {
|
||||
[(UINavigationController*)segue.destinationViewController setToolbarHidden:YES];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController {
|
||||
|
@ -90,6 +136,7 @@ API_AVAILABLE(ios(13.4))
|
|||
}
|
||||
}
|
||||
|
||||
#if !defined(TARGET_OS_VISION) || TARGET_OS_VISION == 0
|
||||
- (BOOL)prefersStatusBarHidden {
|
||||
UIScreen *screen = self.view.window.screen;
|
||||
return CGRectEqualToRect(screen.bounds, self.view.window.bounds);
|
||||
|
@ -98,6 +145,7 @@ API_AVAILABLE(ios(13.4))
|
|||
- (UIStatusBarStyle)preferredStatusBarStyle {
|
||||
return UIStatusBarStyleLightContent;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {
|
||||
return UIRectEdgeAll;
|
||||
|
@ -113,29 +161,8 @@ API_AVAILABLE(ios(13.4))
|
|||
[[NSUserDefaults standardUserDefaults] removeObserver:self forKeyPath:@"trackpad"];
|
||||
}
|
||||
|
||||
- (void)setUpPointingDevice {
|
||||
if (pointingDeviceView) {
|
||||
[pointingDeviceView removeFromSuperview];
|
||||
pointingDeviceView = nil;
|
||||
}
|
||||
|
||||
#ifdef __IPHONE_13_4
|
||||
if (@available(iOS 13.4, *)) {
|
||||
if (interaction == nil) {
|
||||
interaction = [[UIPointerInteraction alloc] initWithDelegate: self];
|
||||
[self.view addInteraction:interaction];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL useTrackPad = [[NSUserDefaults standardUserDefaults] boolForKey:@"trackpad"];
|
||||
Class pointingDeviceClass = useTrackPad ? [TrackPad class] : [TouchScreen class];
|
||||
pointingDeviceView = [[pointingDeviceClass alloc] initWithFrame:self.view.bounds];
|
||||
pointingDeviceView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[self.view insertSubview:pointingDeviceView aboveSubview:self.screenView];
|
||||
if ([UIApplication instancesRespondToSelector:@selector(btcMouseSetRawMode:)]) {
|
||||
[[UIApplication sharedApplication] btcMouseSetRawMode:YES];
|
||||
}
|
||||
- (BOOL)prefersHomeIndicatorAutoHidden {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
|
||||
|
@ -147,6 +174,11 @@ API_AVAILABLE(ios(13.4))
|
|||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)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];
|
||||
|
@ -154,6 +186,7 @@ API_AVAILABLE(ios(13.4))
|
|||
if (keyboardWasVisible) {
|
||||
[self setKeyboardVisible:YES animated:NO];
|
||||
}
|
||||
#endif
|
||||
} else if ([keyPath isEqualToString:@"trackpad"]) {
|
||||
[self setUpPointingDevice];
|
||||
}
|
||||
|
@ -213,7 +246,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 {
|
||||
|
@ -269,7 +304,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 {
|
||||
|
@ -285,10 +324,24 @@ API_AVAILABLE(ios(13.4))
|
|||
}
|
||||
|
||||
- (void)setKeyboardVisible:(BOOL)visible animated:(BOOL)animated {
|
||||
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
|
||||
if (visible) {
|
||||
UISceneSessionActivationRequest *request = [UISceneSessionActivationRequest requestWithRole:UIWindowSceneSessionRoleApplication];
|
||||
request.userActivity = [[NSUserActivity alloc] initWithActivityType:@"net.namedfork.keyboard"];
|
||||
request.userActivity.targetContentIdentifier = @"net.namedfork.keyboard";
|
||||
[[UIApplication sharedApplication] activateSceneSessionForRequest:request errorHandler:^(NSError * _Nonnull error) {
|
||||
NSLog(@"Activation error: %@", error);
|
||||
}];
|
||||
} else {
|
||||
UIScene *keyboardScene = [[AppDelegate sharedInstance] sceneWithName:@"Keyboard"];
|
||||
if (keyboardScene != nil) {
|
||||
[[UIApplication sharedApplication] requestSceneSessionDestruction:keyboardScene.session options:nil errorHandler:nil];
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (self.keyboardVisible == visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"keyboardLayout" options:0 context:NULL];
|
||||
[self loadKeyboardView];
|
||||
|
@ -322,7 +375,7 @@ API_AVAILABLE(ios(13.4))
|
|||
keyboardView.hidden = YES;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)loadKeyboardView {
|
||||
|
@ -364,16 +417,106 @@ API_AVAILABLE(ios(13.4))
|
|||
[[AppDelegate sharedEmulator] keyUp:scancode];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#ifdef __IPHONE_13_4
|
||||
API_AVAILABLE(ios(13.4))
|
||||
@implementation ViewController (PointerInteraction)
|
||||
- (UIPointerRegion *)pointerInteraction:(UIPointerInteraction *)interaction regionForRequest:(UIPointerRegionRequest *)request defaultRegion:(UIPointerRegion *)defaultRegion API_AVAILABLE(ios(13.4)){
|
||||
if (request != nil) {
|
||||
Point mouseLoc = [self mouseLocForCGPoint:request.location];
|
||||
[[AppDelegate sharedEmulator] setMouseX:mouseLoc.h Y:mouseLoc.v];
|
||||
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
|
||||
for (UIPress *press in presses) {
|
||||
[self handlePressEvent:press];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
|
||||
for (UIPress *press in presses) {
|
||||
[self handlePressEvent:press];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
|
||||
for (UIPress *press in presses) {
|
||||
[self handlePressEvent:press];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handlePressEvent:(UIPress *)event {
|
||||
long keycode = event.key.keyCode;
|
||||
int scancode = -1;
|
||||
|
||||
BOOL emulatorIsFrontmost = [AppDelegate sharedEmulator].running && [AppDelegate sharedInstance].window.rootViewController.presentedViewController == nil;
|
||||
BOOL isKeyDown = (event.phase == UIPressPhaseBegan);
|
||||
|
||||
if (keycode >= 0 && keycode < sizeof(usb_to_adb_scancode)) {
|
||||
scancode = usb_to_adb_scancode[keycode];
|
||||
}
|
||||
|
||||
if (scancode == KC_CAPSLOCK) {
|
||||
// caps lock
|
||||
if (isKeyDown && !physicalCapsLocked) {
|
||||
[[AppDelegate sharedEmulator] keyDown:KC_CAPSLOCK];
|
||||
physicalCapsLocked = YES;
|
||||
} else if (isKeyDown && physicalCapsLocked) {
|
||||
[[AppDelegate sharedEmulator] keyUp:KC_CAPSLOCK];
|
||||
physicalCapsLocked = NO;
|
||||
}
|
||||
} else if (scancode >= 0 && emulatorIsFrontmost) {
|
||||
[self _updateCapsLockStatus:event];
|
||||
if (isKeyDown) {
|
||||
[[AppDelegate sharedEmulator] keyDown:scancode];
|
||||
} else {
|
||||
[[AppDelegate sharedEmulator] keyUp:scancode];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_updateCapsLockStatus:(UIPress *)event {
|
||||
BOOL currentCapsLock = (event.key.modifierFlags & UIKeyModifierAlphaShift) != 0;
|
||||
if (currentCapsLock != physicalCapsLocked) {
|
||||
physicalCapsLocked = currentCapsLock;
|
||||
if (physicalCapsLocked) {
|
||||
[[AppDelegate sharedEmulator] keyDown:KC_CAPSLOCK];
|
||||
} else {
|
||||
[[AppDelegate sharedEmulator] keyUp:KC_CAPSLOCK];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Mouse
|
||||
|
||||
- (void)setUpPointingDevice {
|
||||
if (pointingDeviceView) {
|
||||
[pointingDeviceView removeFromSuperview];
|
||||
pointingDeviceView = nil;
|
||||
}
|
||||
|
||||
if (pointerInteraction == nil) {
|
||||
pointerInteraction = [[UIPointerInteraction alloc] initWithDelegate: self];
|
||||
[self.view addInteraction:pointerInteraction];
|
||||
UIHoverGestureRecognizer *hoverGestureRecognizer = [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(hover:)];
|
||||
[self.view addGestureRecognizer:hoverGestureRecognizer];
|
||||
}
|
||||
|
||||
|
||||
#if defined(TARGET_OS_VISION) && TARGET_OS_VISION == 1
|
||||
Class pointingDeviceClass = [TouchScreen class];
|
||||
#else
|
||||
BOOL useTrackPad = [[NSUserDefaults standardUserDefaults] boolForKey:@"trackpad"];
|
||||
Class pointingDeviceClass = useTrackPad ? [TrackPad class] : [TouchScreen class];
|
||||
#endif
|
||||
pointingDeviceView = [[pointingDeviceClass alloc] initWithFrame:self.view.bounds];
|
||||
pointingDeviceView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[self.view insertSubview:pointingDeviceView aboveSubview:self.screenView];
|
||||
if ([UIApplication instancesRespondToSelector:@selector(btcMouseSetRawMode:)]) {
|
||||
[[UIApplication sharedApplication] btcMouseSetRawMode:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (Point)mouseLocForCGPoint:(CGPoint)point {
|
||||
Point mouseLoc;
|
||||
CGRect screenBounds = self.screenView.screenBounds;
|
||||
CGSize screenSize = self.screenView.screenSize;
|
||||
mouseLoc.h = (point.x - screenBounds.origin.x) * (screenSize.width/screenBounds.size.width);
|
||||
mouseLoc.v = (point.y - screenBounds.origin.y) * (screenSize.height/screenBounds.size.height);
|
||||
return mouseLoc;
|
||||
}
|
||||
|
||||
- (UIPointerRegion *)pointerInteraction:(UIPointerInteraction *)interaction regionForRequest:(UIPointerRegionRequest *)request defaultRegion:(UIPointerRegion *)defaultRegion {
|
||||
return defaultRegion;
|
||||
}
|
||||
|
||||
|
@ -381,5 +524,9 @@ API_AVAILABLE(ios(13.4))
|
|||
return [UIPointerStyle hiddenPointerStyle];
|
||||
}
|
||||
|
||||
- (void)hover:(UIHoverGestureRecognizer *)hoverGestureRecognizer {
|
||||
Point mouseLoc = [self mouseLocForCGPoint:[hoverGestureRecognizer locationInView:self.screenView]];
|
||||
[[AppDelegate sharedEmulator] setMouseX:mouseLoc.h Y:mouseLoc.v];
|
||||
}
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
|
80
Mini vMac/VisionSupport.swift
Normal file
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// 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 {
|
||||
PowerMenu()
|
||||
SettingsMenu()
|
||||
|
||||
Button(action: {
|
||||
AppDelegate.shared.showInsertDisk(self)
|
||||
}, label: {
|
||||
Image(systemName: "opticaldiscdrive")
|
||||
})
|
||||
|
||||
Button(action: {
|
||||
self.showKeyboard(self)
|
||||
}, label: {
|
||||
Image(systemName: "keyboard")
|
||||
})
|
||||
}
|
||||
.padding(.all)
|
||||
.glassBackgroundEffect()
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@objc
|
||||
static func adjustToScreenSize() {
|
||||
let screenSize = AppDelegate.emulator.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
|
||||
))
|
||||
}
|
||||
|
||||
@objc
|
||||
func keyboardLayoutMenu() -> UIMenu {
|
||||
let layouts = AppDelegate.shared.keyboardLayoutPaths ?? []
|
||||
let items: [UIMenuElement] = layouts.map({ path in
|
||||
UIDeferredMenuElement.uncached { completion in
|
||||
let layoutId = (path as NSString).lastPathComponent
|
||||
let displayName = (layoutId as NSString).deletingPathExtension
|
||||
let selected = UserDefaults.standard.string(forKey: "keyboardLayout") == layoutId
|
||||
completion([UIAction(title: displayName, state: selected ? .on : .off) { _ in
|
||||
UserDefaults.standard.setValue(layoutId, forKey: "keyboardLayout")
|
||||
}])
|
||||
}
|
||||
})
|
||||
return UIMenu(title: "Layout", options: [], children: items)
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -11,6 +11,6 @@
|
|||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, @"MNVMApplication", NSStringFromClass([AppDelegate class]));
|
||||
return UIApplicationMain(argc, argv, NSStringFromClass([UIApplication class]), NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
* Emulates Mac Plus, Mac II or Mac 128K
|
||||
* Full simulated keyboard (including all Mac keys)
|
||||
* Full sound output
|
||||
* Uses external keyboard if available
|
||||
* Uses external keyboard and mouse/trackpad if available
|
||||
* Regulable emulation speed
|
||||
* Easy(ish) to import/export disk images
|
||||
|
||||
## Requirements
|
||||
|
||||
* iOS 9 or later
|
||||
* iOS/iPadOS 13.4 or later, or visionOS
|
||||
* Previous versions support down to iOS 7
|
||||
* ROM image from Mac Plus, Mac II and/or Mac 128K
|
||||
* Disk images with Mac software
|
||||
|
||||
|
@ -59,9 +60,6 @@ dragging on supported devices.
|
|||
|
||||
If you use a mouse or trackpad on iPad OS 13.4 or newer, it will be used automatically.
|
||||
|
||||
If you have a jailbroken device and [BTC Mouse & Trackpad](http://www.ringwald.ch/cydia/mouse/),
|
||||
Mini vMac will use your bluetooth mouse or trackpad.
|
||||
|
||||
### Settings
|
||||
|
||||
Swipe right with two fingers to show the settings dialog, where you can change
|
||||
|
|