From 9b4aa7a9e71ccaf2bc0449b2a949254c4e7570ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesu=CC=81s=20A=2E=20A=CC=81lvarez?= Date: Sun, 1 May 2016 23:44:47 +0200 Subject: [PATCH] add mouse input --- Mini vMac.xcodeproj/project.pbxproj | 6 ++ Mini vMac/AppDelegate.h | 4 ++ Mini vMac/AppDelegate.m | 27 ++++++++ Mini vMac/Base.lproj/Main.storyboard | 3 + Mini vMac/MYOSGLUE.m | 17 ++++- Mini vMac/ScreenView.h | 3 + Mini vMac/ScreenView.m | 12 +++- Mini vMac/TouchScreen.h | 13 ++++ Mini vMac/TouchScreen.m | 96 ++++++++++++++++++++++++++++ Mini vMac/ViewController.h | 2 + Mini vMac/ViewController.m | 19 ++++++ 11 files changed, 198 insertions(+), 4 deletions(-) create mode 100644 Mini vMac/TouchScreen.h create mode 100644 Mini vMac/TouchScreen.m diff --git a/Mini vMac.xcodeproj/project.pbxproj b/Mini vMac.xcodeproj/project.pbxproj index 88d3f89..8021790 100644 --- a/Mini vMac.xcodeproj/project.pbxproj +++ b/Mini vMac.xcodeproj/project.pbxproj @@ -24,6 +24,7 @@ 28CE8EC31CD4C3B200FE25A8 /* VIAEMDEV.c in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8EB31CD4C3B200FE25A8 /* VIAEMDEV.c */; }; 28CE8ECC1CD4CDC500FE25A8 /* MYOSGLUE.m in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8ECB1CD4CDC500FE25A8 /* MYOSGLUE.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 28CE8ED61CD4F56C00FE25A8 /* ScreenView.m in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8ED51CD4F56C00FE25A8 /* ScreenView.m */; }; + 28D5A3FD1CD6868F001A33F6 /* TouchScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D5A3FC1CD6868E001A33F6 /* TouchScreen.m */; }; 28F676C21CD15E0B00FC6FA6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 28F676C11CD15E0B00FC6FA6 /* main.m */; }; 28F676C51CD15E0B00FC6FA6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 28F676C41CD15E0B00FC6FA6 /* AppDelegate.m */; }; 28F676C81CD15E0B00FC6FA6 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28F676C71CD15E0B00FC6FA6 /* ViewController.m */; }; @@ -77,6 +78,8 @@ 28CE8ECF1CD4D5B900FE25A8 /* INTLCHAR.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = INTLCHAR.h; sourceTree = ""; }; 28CE8ED41CD4F56C00FE25A8 /* ScreenView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreenView.h; sourceTree = ""; }; 28CE8ED51CD4F56C00FE25A8 /* ScreenView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScreenView.m; sourceTree = ""; }; + 28D5A3FB1CD6868E001A33F6 /* TouchScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TouchScreen.h; sourceTree = ""; }; + 28D5A3FC1CD6868E001A33F6 /* TouchScreen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TouchScreen.m; sourceTree = ""; }; 28F676BD1CD15E0B00FC6FA6 /* Mini vMac.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Mini vMac.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 28F676C11CD15E0B00FC6FA6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28F676C31CD15E0B00FC6FA6 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; @@ -179,6 +182,8 @@ 28CE8ECB1CD4CDC500FE25A8 /* MYOSGLUE.m */, 28CE8ED41CD4F56C00FE25A8 /* ScreenView.h */, 28CE8ED51CD4F56C00FE25A8 /* ScreenView.m */, + 28D5A3FB1CD6868E001A33F6 /* TouchScreen.h */, + 28D5A3FC1CD6868E001A33F6 /* TouchScreen.m */, 28F676C61CD15E0B00FC6FA6 /* ViewController.h */, 28F676C71CD15E0B00FC6FA6 /* ViewController.m */, 28F676C91CD15E0B00FC6FA6 /* Main.storyboard */, @@ -285,6 +290,7 @@ 28CE8EBC1CD4C3B200FE25A8 /* ROMEMDEV.c in Sources */, 28CE8EBB1CD4C3B200FE25A8 /* PROGMAIN.c in Sources */, 28F676C81CD15E0B00FC6FA6 /* ViewController.m in Sources */, + 28D5A3FD1CD6868F001A33F6 /* TouchScreen.m in Sources */, 28CE8EC21CD4C3B200FE25A8 /* SONYEMDV.c in Sources */, 28F676C51CD15E0B00FC6FA6 /* AppDelegate.m in Sources */, 28CE8EBE1CD4C3B200FE25A8 /* SCCEMDEV.c in Sources */, diff --git a/Mini vMac/AppDelegate.h b/Mini vMac/AppDelegate.h index 9f595e3..8c57fad 100644 --- a/Mini vMac/AppDelegate.h +++ b/Mini vMac/AppDelegate.h @@ -11,8 +11,12 @@ @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; +@property (assign, nonatomic, getter=isEmulatorRunning) BOOL emulatorRunning; + (instancetype)sharedInstance; +- (void)setMouseX:(NSInteger)x Y:(NSInteger)y; +- (void)moveMouseX:(NSInteger)x Y:(NSInteger)y; +- (void)setMouseButton:(BOOL)down; @end diff --git a/Mini vMac/AppDelegate.m b/Mini vMac/AppDelegate.m index ecc81e3..472981f 100644 --- a/Mini vMac/AppDelegate.m +++ b/Mini vMac/AppDelegate.m @@ -12,7 +12,11 @@ #include "MYOSGLUE.h" IMPORTPROC RunEmulator(void); +IMPORTFUNC blnr GetSpeedStopped(void); IMPORTPROC SetSpeedStopped(blnr stopped); +IMPORTPROC SetMouseButton(blnr down); +IMPORTPROC SetMouseLoc(ui4r h, ui4r v); +IMPORTPROC SetMouseDelta(ui4r dh, ui4r dv); static AppDelegate *sharedAppDelegate = nil; @@ -27,6 +31,7 @@ static AppDelegate *sharedAppDelegate = nil; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + sharedAppDelegate = self; [self performSelector:@selector(runEmulator) withObject:nil afterDelay:1.0]; return YES; } @@ -39,8 +44,30 @@ static AppDelegate *sharedAppDelegate = nil; SetSpeedStopped(falseblnr); } +#pragma mark - Emulation + - (void)runEmulator { RunEmulator(); } +- (BOOL)isEmulatorRunning { + return !GetSpeedStopped(); +} + +- (void)setEmulatorRunning:(BOOL)emulatorRunning { + SetSpeedStopped(emulatorRunning); +} + +- (void)setMouseX:(NSInteger)x Y:(NSInteger)y { + SetMouseLoc(x, y); +} + +- (void)moveMouseX:(NSInteger)x Y:(NSInteger)y { + SetMouseDelta(x, y); +} + +- (void)setMouseButton:(BOOL)down { + SetMouseButton(down); +} + @end diff --git a/Mini vMac/Base.lproj/Main.storyboard b/Mini vMac/Base.lproj/Main.storyboard index 6cbf3f8..1cbeaad 100644 --- a/Mini vMac/Base.lproj/Main.storyboard +++ b/Mini vMac/Base.lproj/Main.storyboard @@ -30,6 +30,9 @@ + + + diff --git a/Mini vMac/MYOSGLUE.m b/Mini vMac/MYOSGLUE.m index 62dd8c1..b902e97 100644 --- a/Mini vMac/MYOSGLUE.m +++ b/Mini vMac/MYOSGLUE.m @@ -853,9 +853,16 @@ LOCALFUNC blnr InitLocationDat(void) { #pragma mark - Mouse -LOCALFUNC blnr MyMoveMouse(si4b h, si4b v) { - // TODO: move mouse - return trueblnr; +GLOBALPROC SetMouseButton(blnr down) { + MyMouseButtonSet(down); +} + +GLOBALPROC SetMouseLoc(ui4r h, ui4r v) { + MyMousePositionSet(h, v); +} + +GLOBALPROC SetMouseDelta(ui4r dh, ui4r dv) { + MyMousePositionSetDelta(dh, dv); } #pragma mark - video out @@ -1551,6 +1558,10 @@ LOCALPROC EnterSpeedStopped(void) { #endif } +GLOBALFUNC blnr GetSpeedStopped(void) { + return CurSpeedStopped; +} + GLOBALPROC SetSpeedStopped(blnr stopped) { CurSpeedStopped = stopped; } diff --git a/Mini vMac/ScreenView.h b/Mini vMac/ScreenView.h index a249212..a09d458 100644 --- a/Mini vMac/ScreenView.h +++ b/Mini vMac/ScreenView.h @@ -10,6 +10,9 @@ @interface ScreenView : UIView +@property (nonatomic, readonly) CGRect screenBounds; +@property (nonatomic, readonly) CGSize screenSize; + + (instancetype)sharedScreenView; - (void)updateScreen:(CGImageRef)screenImage; diff --git a/Mini vMac/ScreenView.m b/Mini vMac/ScreenView.m index 94d1101..18b5707 100644 --- a/Mini vMac/ScreenView.m +++ b/Mini vMac/ScreenView.m @@ -15,17 +15,27 @@ static ScreenView *sharedScreenView = nil; { CGImageRef screenImage; CGRect screenBounds; + CGSize screenSize; } - (void)awakeFromNib { [super awakeFromNib]; sharedScreenView = self; + } + (instancetype)sharedScreenView { return sharedScreenView; } +- (CGRect)screenBounds { + return screenBounds; +} + +- (CGSize)screenSize { + return screenSize; +} + - (void)updateScreen:(CGImageRef)newScreenImage { CGImageRelease(screenImage); screenImage = CGImageRetain(newScreenImage); @@ -33,7 +43,7 @@ static ScreenView *sharedScreenView = nil; } - (void)layoutSubviews { - CGSize screenSize = CGSizeMake(vMacScreenWidth, vMacScreenHeight); + screenSize = CGSizeMake(vMacScreenWidth, vMacScreenHeight); CGRect viewBounds = self.bounds; CGFloat screenScale = MAX(screenSize.width / viewBounds.size.width, screenSize.height / viewBounds.size.height); screenBounds = CGRectMake(0, 0, screenSize.width / screenScale, screenSize.height / screenScale); diff --git a/Mini vMac/TouchScreen.h b/Mini vMac/TouchScreen.h new file mode 100644 index 0000000..f36abb5 --- /dev/null +++ b/Mini vMac/TouchScreen.h @@ -0,0 +1,13 @@ +// +// TouchScreen.h +// Mini vMac for iOS +// +// Created by Jesús A. Álvarez on 18/04/2016. +// Copyright © 2016 namedfork. All rights reserved. +// + +#import + +@interface TouchScreen : UIControl + +@end diff --git a/Mini vMac/TouchScreen.m b/Mini vMac/TouchScreen.m new file mode 100644 index 0000000..3eb2382 --- /dev/null +++ b/Mini vMac/TouchScreen.m @@ -0,0 +1,96 @@ +// +// TouchScreen.m +// Mini vMac for iOS +// +// Created by Jesús A. Álvarez on 18/04/2016. +// Copyright © 2016 namedfork. All rights reserved. +// + +#import "TouchScreen.h" +#import "AppDelegate.h" +#import "ScreenView.h" + +@implementation TouchScreen +{ + // when using absolute mouse mode, button events are processed before the position is updated + NSTimeInterval mouseButtonDelay; + CGPoint previousTouchLoc; + NSTimeInterval previousTouchTime; + NSTimeInterval touchTimeThreshold; + CGFloat touchDistanceThreshold; + NSMutableSet *currentTouches; +} + +- (instancetype)initWithFrame:(CGRect)frame { + if ((self = [super initWithFrame:frame])) { + mouseButtonDelay = 0.05; + touchTimeThreshold = 0.25; + touchDistanceThreshold = 16; + currentTouches = [NSMutableSet setWithCapacity:4]; + } + return self; +} + +- (Point)mouseLocForCGPoint:(CGPoint)point { + Point mouseLoc; + CGRect screenBounds = [ScreenView sharedScreenView].screenBounds; + CGSize screenSize = [ScreenView sharedScreenView].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; +} + +- (void)mouseDown { + [[AppDelegate sharedInstance] setMouseButton:YES]; +} + +- (void)mouseUp { + [[AppDelegate sharedInstance] setMouseButton:NO]; +} + +- (CGPoint)effectiveTouchPointForEvent:(UIEvent *)event { + CGPoint touchLoc = [[event touchesForView:self].anyObject locationInView:self]; + if (event.timestamp - previousTouchTime < touchTimeThreshold && + fabs(previousTouchLoc.x - touchLoc.x) < touchDistanceThreshold && + fabs(previousTouchLoc.y - touchLoc.y) < touchDistanceThreshold) + return previousTouchLoc; + previousTouchLoc = touchLoc; + previousTouchTime = event.timestamp; + return touchLoc; +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + [currentTouches unionSet:touches]; + if (![AppDelegate sharedInstance].emulatorRunning) return; + CGPoint touchLoc = [self effectiveTouchPointForEvent:event]; + Point mouseLoc = [self mouseLocForCGPoint:touchLoc]; + [[AppDelegate sharedInstance] setMouseX:mouseLoc.h Y:mouseLoc.v]; + [self performSelector:@selector(mouseDown) withObject:nil afterDelay:mouseButtonDelay]; + previousTouchLoc = touchLoc; + previousTouchTime = event.timestamp; +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + if (![AppDelegate sharedInstance].emulatorRunning) return; + CGPoint touchLoc = [self effectiveTouchPointForEvent:event]; + Point mouseLoc = [self mouseLocForCGPoint:touchLoc]; + [[AppDelegate sharedInstance] setMouseX:mouseLoc.h Y:mouseLoc.v]; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + [currentTouches minusSet:touches]; + if (![AppDelegate sharedInstance].emulatorRunning) return; + if (currentTouches.count > 0) return; + CGPoint touchLoc = [self effectiveTouchPointForEvent:event]; + Point mouseLoc = [self mouseLocForCGPoint:touchLoc]; + [[AppDelegate sharedInstance] setMouseX:mouseLoc.h Y:mouseLoc.v]; + [self performSelector:@selector(mouseUp) withObject:nil afterDelay:mouseButtonDelay]; + previousTouchLoc = touchLoc; + previousTouchTime = event.timestamp; +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + [self touchesEnded:touches withEvent:event]; +} + +@end diff --git a/Mini vMac/ViewController.h b/Mini vMac/ViewController.h index ec191f5..d0e1c6d 100644 --- a/Mini vMac/ViewController.h +++ b/Mini vMac/ViewController.h @@ -7,9 +7,11 @@ // #import +#import "ScreenView.h" @interface ViewController : UIViewController +@property (weak, nonatomic) IBOutlet ScreenView *screenView; @end diff --git a/Mini vMac/ViewController.m b/Mini vMac/ViewController.m index 058f670..ec0c71c 100644 --- a/Mini vMac/ViewController.m +++ b/Mini vMac/ViewController.m @@ -7,15 +7,34 @@ // #import "ViewController.h" +#import "TouchScreen.h" @interface ViewController () @end @implementation ViewController +{ + UIControl *pointingDeviceView; +} - (BOOL)prefersStatusBarHidden { return YES; } +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self setUpPointingDevice]; +} + +- (void)setUpPointingDevice { + if (pointingDeviceView) { + [pointingDeviceView removeFromSuperview]; + pointingDeviceView = nil; + } + pointingDeviceView = [[TouchScreen alloc] initWithFrame:self.view.bounds]; + pointingDeviceView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self.view insertSubview:pointingDeviceView aboveSubview:self.screenView]; +} + @end