diff --git a/Mini vMac WatchKit App/Assets.xcassets/AppIcon.appiconset/Contents.json b/Mini vMac WatchKit App/Assets.xcassets/AppIcon.appiconset/Contents.json index 3c0e08b..3d8e1be 100644 --- a/Mini vMac WatchKit App/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Mini vMac WatchKit App/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -15,12 +15,14 @@ "subtype" : "42mm" }, { + "filename" : "Icon 7.png", "idiom" : "watch", "role" : "companionSettings", "scale" : "2x", "size" : "29x29" }, { + "filename" : "Icon 6.png", "idiom" : "watch", "role" : "companionSettings", "scale" : "3x", diff --git a/Mini vMac WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon 6.png b/Mini vMac WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon 6.png new file mode 100644 index 0000000..9d75b34 Binary files /dev/null and b/Mini vMac WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon 6.png differ diff --git a/Mini vMac WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon 7.png b/Mini vMac WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon 7.png new file mode 100644 index 0000000..d069247 Binary files /dev/null and b/Mini vMac WatchKit App/Assets.xcassets/AppIcon.appiconset/Icon 7.png differ diff --git a/Mini vMac WatchKit Extension/InterfaceController.h b/Mini vMac WatchKit Extension/InterfaceController.h index 9d4ae0e..4c6c2ba 100644 --- a/Mini vMac WatchKit Extension/InterfaceController.h +++ b/Mini vMac WatchKit Extension/InterfaceController.h @@ -9,11 +9,14 @@ #import #import #import +#import "EmulatorProtocol.h" @class WCSession; @interface InterfaceController : WKInterfaceController +@property (class, readonly, strong) id sharedEmulator NS_SWIFT_NAME(emulator); + - (void)sessionReachabilityDidChange:(WCSession *)session; @end diff --git a/Mini vMac WatchKit Extension/InterfaceController.m b/Mini vMac WatchKit Extension/InterfaceController.m index df054fe..819a3ed 100644 --- a/Mini vMac WatchKit Extension/InterfaceController.m +++ b/Mini vMac WatchKit Extension/InterfaceController.m @@ -11,8 +11,10 @@ @import ObjectiveC.runtime; @import WatchConnectivity; +#import "UIKit+Watch.h" #import "InterfaceController.h" #import "EmulatorProtocol.h" +#import "TrackPad.h" @interface NSObject (fs_override) +(id)sharedApplication; @@ -32,15 +34,19 @@ -(void)setContentsScale:(CGFloat)value; -(void)setContentsGravity:(NSString*)gravity; -(void)setMinificationFilter:(NSString*)filter; +-(void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(NSUInteger)controlEvents; +-(void)setIdleTimerDisabled:(BOOL)disabled; @end @interface InterfaceController () @end +static NSObject *sharedEmulator = nil; + @implementation InterfaceController { - NSObject *emulator; + } + (void)load { @@ -52,6 +58,10 @@ } } ++ (id)sharedEmulator { + return sharedEmulator; +} + - (void)awakeWithContext:(id)context { [super awakeWithContext:context]; } @@ -71,7 +81,7 @@ } -- (id)fullScreenView { +- (UIView*)fullScreenView { id parentView = [[[[[[NSClassFromString(@"UIApplication") sharedApplication] keyWindow] rootViewController] viewControllers] firstObject] view]; id view = [self findDescendantViewOfClass:NSClassFromString(@"SPFullScreenView") inView:parentView]; // watchOS 5 if (view == nil) { @@ -94,21 +104,23 @@ - (void)didAppear { [self hideTimeLabel]; - if (emulator == nil) { + if (sharedEmulator == nil) { [self loadAndStartEmulator]; + } else { + sharedEmulator.running = YES; } } - (void)willActivate { if ([WKExtension sharedExtension].applicationState == WKApplicationStateActive) { - emulator.running = YES; + sharedEmulator.running = YES; } } - (void)didDeactivate { // This method is called when watch view controller is no longer visible [super didDeactivate]; - emulator.running = NO; + sharedEmulator.running = NO; } - (void)sessionReachabilityDidChange:(WCSession *)session { @@ -116,18 +128,26 @@ } - (void)loadAndStartEmulator { + UIView *fullScreenView = [self fullScreenView]; Class emulatorClass = NSClassFromString(@"MacPlus4MEmulator"); - emulator = [emulatorClass new]; - emulator.rootViewController = nil; - emulator.showAlert = ^(NSString *title, NSString *message) { + sharedEmulator = [emulatorClass new]; + sharedEmulator.rootViewController = nil; + sharedEmulator.showAlert = ^(NSString *title, NSString *message) { NSLog(@"Alert: %@ - %@", title, message); }; - emulator.dataPath = [NSBundle mainBundle].resourcePath; - emulator.screenLayer = [[self fullScreenView] layer]; - emulator.speed = emulator.initialSpeed; - [emulator.screenLayer setContentsGravity:@"CAGravityResizeAspectFill"]; - [emulator.screenLayer setAffineTransform:CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI_2), 0.375, 0.375)]; - [emulator.screenLayer setMinificationFilter:@"CAFilterTrilinear"]; - [emulator performSelector:@selector(run) withObject:nil afterDelay:0.1]; + sharedEmulator.dataPath = [NSBundle mainBundle].resourcePath; + sharedEmulator.screenLayer = fullScreenView.layer; + sharedEmulator.speed = sharedEmulator.initialSpeed; + [sharedEmulator.screenLayer setContentsGravity:@"CAGravityResizeAspectFill"]; + [sharedEmulator.screenLayer setAffineTransform:CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI_2), 0.375, 0.375)]; + [sharedEmulator.screenLayer setMinificationFilter:@"CAFilterTrilinear"]; + [sharedEmulator performSelector:@selector(run) withObject:nil afterDelay:0.1]; + + id app = [NSClassFromString(@"UIApplication") sharedApplication]; + [app setIdleTimerDisabled:YES]; + + TrackPad *trackpad = [[TrackPad alloc] initWithFrame:fullScreenView.bounds]; + [fullScreenView addSubview:trackpad]; } + @end diff --git a/Mini vMac WatchKit Extension/UIKit+Watch.h b/Mini vMac WatchKit Extension/UIKit+Watch.h new file mode 100644 index 0000000..5615cc7 --- /dev/null +++ b/Mini vMac WatchKit Extension/UIKit+Watch.h @@ -0,0 +1,46 @@ +// +// UIKit+Watch.h +// Mini vMac +// +// Created by Jesús A. Álvarez on 2024-03-27. +// Copyright © 2024 namedfork. All rights reserved. +// + +#ifndef UIKit_Watch_h +#define UIKit_Watch_h + +#import + +NS_ASSUME_NONNULL_BEGIN + + +@interface UIResponder : NSObject + +@end + +@interface UIView : UIResponder +@property(nonatomic,getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled; +@property(nonatomic) CGRect bounds; + +- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER; + +@end + +@interface UITouch : NSObject + +@property(nonatomic,readonly) CGFloat force; + +- (CGPoint)locationInView:(nullable UIView *)view; +- (CGPoint)previousLocationInView:(nullable UIView *)view; + +@end + +@interface UIEvent : NSObject + +@property(nonatomic,readonly) NSTimeInterval timestamp; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* UIKit_h */ diff --git a/Mini vMac.xcodeproj/project.pbxproj b/Mini vMac.xcodeproj/project.pbxproj index 4b0d359..527ffbf 100644 --- a/Mini vMac.xcodeproj/project.pbxproj +++ b/Mini vMac.xcodeproj/project.pbxproj @@ -45,6 +45,8 @@ 289673912BB4947A0014D8E7 /* MacPlus4M_WatchOS.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 289673422BB209DB0014D8E7 /* MacPlus4M_WatchOS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 289673942BB494FB0014D8E7 /* Mini vMac WatchKit Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 2896738E2BB493F80014D8E7 /* Mini vMac WatchKit Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 289673972BB4958D0014D8E7 /* Mini vMac WatchKit App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 289673742BB492400014D8E7 /* Mini vMac WatchKit App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 2896739B2BB4A2E80014D8E7 /* TrackPad.m in Sources */ = {isa = PBXBuildFile; fileRef = 28BA89841CE73E7200A98104 /* TrackPad.m */; }; + 2896739E2BB4A90A0014D8E7 /* disk1.dsk in Resources */ = {isa = PBXBuildFile; fileRef = 2896739D2BB4A90A0014D8E7 /* disk1.dsk */; }; 289710C31CFB11BF0089D463 /* MYOSGLUE.m in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8ECB1CD4CDC500FE25A8 /* MYOSGLUE.m */; }; 289710DC1CFB12240089D463 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 289710D81CFB121F0089D463 /* Icon.png */; }; 289710DD1CFB12240089D463 /* Icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 289710D91CFB121F0089D463 /* Icon@2x.png */; }; @@ -365,6 +367,8 @@ 289673842BB4937D0014D8E7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 289673852BB4937D0014D8E7 /* Interface.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Interface.storyboard; sourceTree = ""; }; 2896738E2BB493F80014D8E7 /* Mini vMac WatchKit Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Mini vMac WatchKit Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + 2896739C2BB4A4170014D8E7 /* UIKit+Watch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIKit+Watch.h"; sourceTree = ""; }; + 2896739D2BB4A90A0014D8E7 /* disk1.dsk */ = {isa = PBXFileReference; lastKnownFileType = file; path = disk1.dsk; sourceTree = ""; }; 289710D41CFB11BF0089D463 /* Mac128K.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Mac128K.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 289710D61CFB121F0089D463 /* CNFUDOSG.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNFUDOSG.h; sourceTree = ""; }; 289710D71CFB121F0089D463 /* CNFUDALL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNFUDALL.h; sourceTree = ""; }; @@ -652,6 +656,8 @@ 2896737F2BB4937D0014D8E7 /* InterfaceController.h */, 289673802BB4937D0014D8E7 /* InterfaceController.m */, 289673812BB4937D0014D8E7 /* vMac.rom */, + 2896739D2BB4A90A0014D8E7 /* disk1.dsk */, + 2896739C2BB4A4170014D8E7 /* UIKit+Watch.h */, ); path = "Mini vMac WatchKit Extension"; sourceTree = ""; @@ -1320,6 +1326,7 @@ buildActionMask = 2147483647; files = ( 2896738A2BB493A90014D8E7 /* Assets.xcassets in Resources */, + 2896739E2BB4A90A0014D8E7 /* disk1.dsk in Resources */, 2896738D2BB493B20014D8E7 /* vMac.rom in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1594,6 +1601,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2896739B2BB4A2E80014D8E7 /* TrackPad.m in Sources */, 2896738B2BB493AF0014D8E7 /* InterfaceController.m in Sources */, 2896738C2BB493AF0014D8E7 /* ExtensionDelegate.m in Sources */, ); diff --git a/Mini vMac/TrackPad.h b/Mini vMac/TrackPad.h index 8fb6c25..006bd46 100644 --- a/Mini vMac/TrackPad.h +++ b/Mini vMac/TrackPad.h @@ -8,6 +8,11 @@ #import +#if TARGET_OS_WATCH +#import "UIKit+Watch.h" +@interface TrackPad : UIView +#else @interface TrackPad : UIControl +#endif @end diff --git a/Mini vMac/TrackPad.m b/Mini vMac/TrackPad.m index 88dbeee..3e19e9d 100644 --- a/Mini vMac/TrackPad.m +++ b/Mini vMac/TrackPad.m @@ -7,8 +7,14 @@ // #import "TrackPad.h" +#if TARGET_OS_WATCH +#import "InterfaceController.h" +#define AppDelegate InterfaceController +#define AudioServicesPlaySystemSound +#else #import "AppDelegate.h" @import AudioToolbox; +#endif #define TRACKPAD_ACCEL_N 1 #define TRACKPAD_ACCEL_T 0.2 @@ -36,6 +42,7 @@ return self; } +#if !TARGET_OS_WATCH - (void)willMoveToSuperview:(UIView *)newSuperview { [super willMoveToSuperview:newSuperview]; @try { @@ -44,9 +51,14 @@ supportsForceTouch = NO; } } +#endif - (BOOL)isMouseEvent:(UIEvent *)event { +#if TARGET_OS_WATCH + return NO; +#else return event.buttonMask != 0; +#endif } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { @@ -54,7 +66,7 @@ [self startDragging]; return; } - + [currentTouches unionSet:touches]; if (currentTouches.count == 1) { [self firstTouchBegan:touches.anyObject withEvent:event];