From 4b5acd430ac11bd7cd13093aa6a7558af2b4027f Mon Sep 17 00:00:00 2001 From: osy Date: Sat, 28 Mar 2020 23:17:07 -0700 Subject: [PATCH 01/14] CocoaSpice: fixed debug logging --- CocoaSpice/CSMain.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CocoaSpice/CSMain.m b/CocoaSpice/CSMain.m index b0fb5fc16..ba169970b 100644 --- a/CocoaSpice/CSMain.m +++ b/CocoaSpice/CSMain.m @@ -100,7 +100,7 @@ - (void)dealloc { - (void)spiceSetDebug:(BOOL)enabled { spice_util_set_debug(enabled); - g_log_set_default_handler(logHandler, NULL); + g_log_set_handler(NULL, G_LOG_LEVEL_MASK, logHandler, NULL); } - (BOOL)spiceStart { From 480491115d8c6e6a3d4c0ff07240b774f1eb63fd Mon Sep 17 00:00:00 2001 From: osy Date: Sat, 28 Mar 2020 23:17:33 -0700 Subject: [PATCH 02/14] CocoaSpice: allow cursor to be force hidden --- CocoaSpice/CSInput.h | 1 + CocoaSpice/CSInput.m | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CocoaSpice/CSInput.h b/CocoaSpice/CSInput.h index 98159b082..ac87819fe 100644 --- a/CocoaSpice/CSInput.h +++ b/CocoaSpice/CSInput.h @@ -50,6 +50,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) BOOL disableInputs; @property (nonatomic, readonly) CGSize cursorSize; @property (nonatomic, assign) CGSize displaySize; +@property (nonatomic, assign) BOOL inhibitCursor; - (void)sendKey:(SendKeyType)type code:(int)scancode; - (void)sendPause:(SendKeyType)type; diff --git a/CocoaSpice/CSInput.m b/CocoaSpice/CSInput.m index 55d8a03e3..824ea4190 100644 --- a/CocoaSpice/CSInput.m +++ b/CocoaSpice/CSInput.m @@ -521,7 +521,7 @@ - (void)drawCursor:(const void *)buffer { } - (BOOL)visible { - return self.hasCursor && !_cursorHidden; + return !self.inhibitCursor && self.hasCursor && !_cursorHidden; } - (CGPoint)viewportOrigin { From 7599b9fa00caa68532b7f3afb85c6c6c495a1e10 Mon Sep 17 00:00:00 2001 From: osy Date: Sat, 28 Mar 2020 23:19:12 -0700 Subject: [PATCH 03/14] vm: remove redundent "touchscreen" property --- Managers/UTMQemuSystem.m | 17 ++++++++++------- Views/VMCursor.m | 4 ++-- Views/VMDisplayMetalViewController+Touch.m | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Managers/UTMQemuSystem.m b/Managers/UTMQemuSystem.m index 83686a126..e57402362 100644 --- a/Managers/UTMQemuSystem.m +++ b/Managers/UTMQemuSystem.m @@ -48,13 +48,11 @@ - (void)targetSpecificConfiguration { [self pushArgv:@"-device"]; [self pushArgv:@"usb-ehci"]; [self pushArgv:@"-device"]; + [self pushArgv:@"usb-mouse"]; + [self pushArgv:@"-device"]; + [self pushArgv:@"usb-mouse"]; + [self pushArgv:@"-device"]; [self pushArgv:@"usb-kbd"]; - if (!self.configuration.inputTouchscreenMode) { - // virt requires USB mouse - // if we're in touchscreen mode, we already added usb-tablet - [self pushArgv:@"-device"]; - [self pushArgv:@"usb-mouse"]; - } for (NSUInteger i = 0; i < self.configuration.countDrives; i++) { UTMDiskImageType type = [self.configuration driveImageTypeForIndex:i]; if (type == UTMDiskImageTypeDisk || type == UTMDiskImageTypeCD) { @@ -177,9 +175,14 @@ - (void)argsFromConfiguration { [self pushArgv:@"-nic"]; [self pushArgv:@"none"]; } - if (self.configuration.inputTouchscreenMode) { + // usb input if not legacy + if (1) { // TODO: implement legacy mode + [self pushArgv:@"-device"]; + [self pushArgv:@"usb-ehci"]; [self pushArgv:@"-device"]; [self pushArgv:@"usb-tablet"]; + [self pushArgv:@"-device"]; + [self pushArgv:@"usb-mouse"]; } if (self.snapshot) { [self pushArgv:@"-loadvm"]; diff --git a/Views/VMCursor.m b/Views/VMCursor.m index 2bb02b332..838a5682c 100644 --- a/Views/VMCursor.m +++ b/Views/VMCursor.m @@ -66,14 +66,14 @@ - (void)setCenter:(CGPoint)center { - (void)startMovement:(CGPoint)startPoint { _start = startPoint; - if (_controller.touchscreen) { + if (!_controller.serverModeCursor) { _lastCenter = startPoint; _center = startPoint; } } - (void)updateMovement:(CGPoint)point { - if (!_controller.touchscreen) { + if (_controller.serverModeCursor) { // translate point to relative to last center CGPoint adj = CGPointMake(point.x - _start.x, point.y - _start.y); _start = point; diff --git a/Views/VMDisplayMetalViewController+Touch.m b/Views/VMDisplayMetalViewController+Touch.m index 5e03b1fdd..f380b3eec 100644 --- a/Views/VMDisplayMetalViewController+Touch.m +++ b/Views/VMDisplayMetalViewController+Touch.m @@ -283,7 +283,7 @@ - (CGPoint)moveMouseRelative:(CGPoint)translation { } - (void)mouseClick:(SendButtonType)button location:(CGPoint)location { - if (self.touchscreen) { + if (!self.serverModeCursor) { _cursor.center = location; } [self.vmInput sendMouseButton:button pressed:YES point:CGPointZero]; From 5580dc61296cf2c4c3dba72a677a9d836ec6fae5 Mon Sep 17 00:00:00 2001 From: osy Date: Sat, 28 Mar 2020 23:27:52 -0700 Subject: [PATCH 04/14] settings: add mouse mode --- UTM/Info.plist | 2 + UTM/Settings.bundle/Root.plist | 70 ++++++++++++++++++++++ Views/VMDisplayMetalViewController+Touch.h | 9 +++ Views/VMDisplayMetalViewController+Touch.m | 21 +++++++ 4 files changed, 102 insertions(+) diff --git a/UTM/Info.plist b/UTM/Info.plist index 14a3fa9d6..b31d6da3c 100644 --- a/UTM/Info.plist +++ b/UTM/Info.plist @@ -88,5 +88,7 @@ UIViewControllerBasedStatusBarAppearance + UIApplicationSupportsIndirectInputEvents + diff --git a/UTM/Settings.bundle/Root.plist b/UTM/Settings.bundle/Root.plist index 0af569a36..a93c64b08 100644 --- a/UTM/Settings.bundle/Root.plist +++ b/UTM/Settings.bundle/Root.plist @@ -144,6 +144,76 @@ 1 + + Type + PSGroupSpecifier + Title + Cursor + + + Type + PSMultiValueSpecifier + Title + Touch Input + Key + MouseTouchType + DefaultValue + 0 + Titles + + Drag cursor + Touch mode (always show cursor) + Touch mode (try hiding cursor) + + Values + + 0 + 1 + 2 + + + + Type + PSMultiValueSpecifier + Title + Apple Pencil Input + Key + MousePencilType + DefaultValue + 2 + Titles + + Drag cursor + Tablet mode (always show cursor) + Tablet mode (try hiding cursor) + + Values + + 0 + 1 + 2 + + + + Type + PSMultiValueSpecifier + Title + Touchpad/Mouse Input + Key + MouseIndirectType + DefaultValue + 1 + Titles + + Drag cursor + Follow cursor + + Values + + 0 + 1 + + diff --git a/Views/VMDisplayMetalViewController+Touch.h b/Views/VMDisplayMetalViewController+Touch.h index 7fed6b50f..20bb10756 100644 --- a/Views/VMDisplayMetalViewController+Touch.h +++ b/Views/VMDisplayMetalViewController+Touch.h @@ -25,6 +25,12 @@ typedef NS_ENUM(NSInteger, VMGestureType) { VMGestureTypeMax }; +typedef NS_ENUM(NSInteger, VMMouseType) { + VMMouseTypeRelative, + VMMouseTypeAbsolute, + VMMouseTypeAbsoluteHideCursor +}; + NS_ASSUME_NONNULL_BEGIN @interface VMDisplayMetalViewController (Gestures) @@ -34,6 +40,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) VMGestureType twoFingerPanType; @property (nonatomic, readonly) VMGestureType twoFingerScrollType; @property (nonatomic, readonly) VMGestureType threeFingerPanType; +@property (nonatomic, readonly) VMMouseType touchMouseType; +@property (nonatomic, readonly) VMMouseType pencilMouseType; +@property (nonatomic, readonly) VMMouseType indirectMouseType; - (void)initTouch; diff --git a/Views/VMDisplayMetalViewController+Touch.m b/Views/VMDisplayMetalViewController+Touch.m index f380b3eec..7adb8f73d 100644 --- a/Views/VMDisplayMetalViewController+Touch.m +++ b/Views/VMDisplayMetalViewController+Touch.m @@ -112,6 +112,27 @@ - (VMGestureType)threeFingerPanType { return [self gestureTypeForSetting:@"GestureThreePan"]; } +- (VMMouseType)mouseTypeForSetting:(NSString *)key { + NSInteger integer = [self integerForSetting:key]; + if (integer < VMGestureTypeNone || integer >= VMGestureTypeMax) { + return VMMouseTypeRelative; + } else { + return (VMMouseType)integer; + } +} + +- (VMMouseType)touchMouseType { + return [self mouseTypeForSetting:@"MouseTouchType"]; +} + +- (VMMouseType)pencilMouseType { + return [self mouseTypeForSetting:@"MousePencilType"]; +} + +- (VMMouseType)indirectMouseType { + return [self mouseTypeForSetting:@"MouseIndirectType"]; +} + #pragma mark - Converting view points to VM display points static CGRect CGRectClipToBounds(CGRect rect1, CGRect rect2) { From a0eea872242907f8327f82c57bee4a3a12a02250 Mon Sep 17 00:00:00 2001 From: osy Date: Sat, 28 Mar 2020 23:28:21 -0700 Subject: [PATCH 05/14] vm: switch mouse mode on touch change --- Views/VMDisplayMetalViewController+Touch.m | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Views/VMDisplayMetalViewController+Touch.m b/Views/VMDisplayMetalViewController+Touch.m index 7adb8f73d..2fb755ef2 100644 --- a/Views/VMDisplayMetalViewController+Touch.m +++ b/Views/VMDisplayMetalViewController+Touch.m @@ -448,4 +448,39 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecogni } } +#pragma mark - Touch type + +- (VMMouseType)touchTypeToMouseType:(UITouchType)type { + switch (type) { + case UITouchTypeDirect: { + return self.touchMouseType; + } + case UITouchTypePencil: { + return self.pencilMouseType; + } + case UITouchTypeIndirect: + default: { // covers UITouchTypeIndirectPointer + return self.indirectMouseType; + } + } +} + +- (void)switchMouseType:(VMMouseType)type { + BOOL shouldHideCursor = (type == VMMouseTypeAbsoluteHideCursor); + BOOL shouldUseServerMouse = (type == VMMouseTypeRelative); + self.vmInput.inhibitCursor = shouldHideCursor; + if (shouldUseServerMouse != self.vmInput.serverModeCursor) { + NSLog(@"Switching mouse mode to server:%d for type:%ld", shouldUseServerMouse, type); + [self.vmInput requestMouseMode:shouldUseServerMouse]; + } +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + for (UITouch *touch in touches) { + VMMouseType type = [self touchTypeToMouseType:touch.type]; + [self switchMouseType:type]; + } + [super touchesBegan:touches withEvent:event]; +} + @end From d73380fdc9e5e2ce79e834557092180a34858300 Mon Sep 17 00:00:00 2001 From: osy Date: Sat, 28 Mar 2020 23:29:09 -0700 Subject: [PATCH 06/14] settings: rename drag cursor to avoid confusion --- UTM/Settings.bundle/Root.plist | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/UTM/Settings.bundle/Root.plist b/UTM/Settings.bundle/Root.plist index a93c64b08..62c7ed1ea 100644 --- a/UTM/Settings.bundle/Root.plist +++ b/UTM/Settings.bundle/Root.plist @@ -50,7 +50,7 @@ Titles Disabled - Drag Cursor + Click & Hold Right Click Values @@ -93,7 +93,7 @@ Disabled Move Screen - Drag Cursor + Click & Hold Values @@ -135,7 +135,7 @@ Disabled Move Screen - Drag Cursor + Click & Hold Values From eea9fd23c0663d22fa0806094688bdac742b6035 Mon Sep 17 00:00:00 2001 From: osy Date: Sun, 29 Mar 2020 16:43:58 -0700 Subject: [PATCH 07/14] configuration: implemented input vm settings Removed un-used/reworked settings. Added legacy mode switch. Added link to app settings. --- Configuration/UTMConfiguration.h | 3 +- Configuration/UTMConfiguration.m | 23 +++--- .../VMConfigInputViewController.h | 9 +-- .../VMConfigInputViewController.m | 59 +++----------- Managers/UTMQemuSystem.m | 2 +- UTM/Base.lproj/Main.storyboard | 80 +++++++------------ Views/VMDisplayMetalViewController.h | 1 - Views/VMDisplayMetalViewController.m | 4 - 8 files changed, 54 insertions(+), 127 deletions(-) diff --git a/Configuration/UTMConfiguration.h b/Configuration/UTMConfiguration.h index 3ffd9fa97..04a63878f 100644 --- a/Configuration/UTMConfiguration.h +++ b/Configuration/UTMConfiguration.h @@ -67,8 +67,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) BOOL displayZoomScale; @property (nonatomic, assign) BOOL displayZoomLetterBox; -@property (nonatomic, assign) BOOL inputTouchscreenMode; -@property (nonatomic, assign) BOOL inputDirect; +@property (nonatomic, assign) BOOL inputLegacy; @property (nonatomic, assign) BOOL networkEnabled; @property (nonatomic, assign) BOOL networkLocalhostOnly; diff --git a/Configuration/UTMConfiguration.m b/Configuration/UTMConfiguration.m index 0ba711d5c..a6ccdcd29 100644 --- a/Configuration/UTMConfiguration.m +++ b/Configuration/UTMConfiguration.m @@ -44,6 +44,7 @@ const NSString *const kUTMConfigTouchscreenModeKey = @"TouchscreenMode"; const NSString *const kUTMConfigDirectInputKey = @"DirectInput"; +const NSString *const kUTMConfigInputLegacyKey = @"InputLegacy"; const NSString *const kUTMConfigNetworkEnabledKey = @"NetworkEnabled"; const NSString *const kUTMConfigLocalhostOnlyKey = @"LocalhostOnly"; @@ -1362,6 +1363,12 @@ - (void)migrateConfigurationIfNecessary { [obj removeObjectForKey:kUTMConfigCdromKey]; } }]; + // Migrate input settings + [_rootDict[kUTMConfigInputKey] removeObjectForKey:kUTMConfigTouchscreenModeKey]; + [_rootDict[kUTMConfigInputKey] removeObjectForKey:kUTMConfigDirectInputKey]; + if (!_rootDict[kUTMConfigInputKey][kUTMConfigInputLegacyKey]) { + self.inputLegacy = NO; + } } #pragma mark - Initialization @@ -1563,20 +1570,12 @@ - (BOOL)displayZoomLetterBox { return [_rootDict[kUTMConfigDisplayKey][kUTMConfigZoomLetterboxKey] boolValue]; } -- (void)setInputTouchscreenMode:(BOOL)inputTouchscreenMode { - _rootDict[kUTMConfigInputKey][kUTMConfigTouchscreenModeKey] = @(inputTouchscreenMode); -} - -- (BOOL)inputTouchscreenMode { - return [_rootDict[kUTMConfigInputKey][kUTMConfigTouchscreenModeKey] boolValue]; -} - -- (void)setInputDirect:(BOOL)inputDirect { - _rootDict[kUTMConfigInputKey][kUTMConfigDirectInputKey] = @(inputDirect); +- (void)setInputLegacy:(BOOL)inputDirect { + _rootDict[kUTMConfigInputKey][kUTMConfigInputLegacyKey] = @(inputDirect); } -- (BOOL)inputDirect { - return [_rootDict[kUTMConfigInputKey][kUTMConfigDirectInputKey] boolValue]; +- (BOOL)inputLegacy { + return [_rootDict[kUTMConfigInputKey][kUTMConfigInputLegacyKey] boolValue]; } - (void)setNetworkEnabled:(BOOL)networkEnabled { diff --git a/ConfigurationViews/VMConfigInputViewController.h b/ConfigurationViews/VMConfigInputViewController.h index 130ee78b3..50bcb8f01 100644 --- a/ConfigurationViews/VMConfigInputViewController.h +++ b/ConfigurationViews/VMConfigInputViewController.h @@ -21,13 +21,10 @@ NS_ASSUME_NONNULL_BEGIN @interface VMConfigInputViewController : VMConfigViewController -@property (weak, nonatomic) IBOutlet UITableViewCell *pointerStyleTouchscreenCell; -@property (weak, nonatomic) IBOutlet UITableViewCell *pointerStyleTrackpadCell; -@property (weak, nonatomic) IBOutlet UITableViewCell *inputReceiverDirectCell; -@property (weak, nonatomic) IBOutlet UITableViewCell *inputReceiverServerCell; +@property (weak, nonatomic) IBOutlet UITableViewCell *openSettingsCell; +@property (weak, nonatomic) IBOutlet UISwitch *legacyModeSwitch; -@property (nonatomic, assign) BOOL inputTouchscreenMode; -@property (nonatomic, assign) BOOL inputDirect; +- (IBAction)legacyModeChanged:(UISwitch *)sender; @end diff --git a/ConfigurationViews/VMConfigInputViewController.m b/ConfigurationViews/VMConfigInputViewController.m index 160f875da..657407e90 100644 --- a/ConfigurationViews/VMConfigInputViewController.m +++ b/ConfigurationViews/VMConfigInputViewController.m @@ -23,63 +23,26 @@ @interface VMConfigInputViewController () @implementation VMConfigInputViewController -- (void)viewDidLoad { - [super viewDidLoad]; - // FIXME: remove this warning - [self showUnimplementedAlert]; -} - - (void)refreshViewFromConfiguration { [super refreshViewFromConfiguration]; - self.inputTouchscreenMode = self.configuration.inputTouchscreenMode; - self.inputDirect = self.configuration.inputDirect; + self.legacyModeSwitch.on = self.configuration.inputLegacy; } -#pragma mark - Properties +#pragma mark - Table delegate -- (void)setInputTouchscreenMode:(BOOL)inputTouchscreenMode { - _inputTouchscreenMode = inputTouchscreenMode; - self.configuration.inputTouchscreenMode = inputTouchscreenMode; - if (inputTouchscreenMode) { - [self.pointerStyleTouchscreenCell setAccessoryType:UITableViewCellAccessoryCheckmark]; - [self.pointerStyleTrackpadCell setAccessoryType:UITableViewCellAccessoryNone]; - [self.pointerStyleTouchscreenCell setSelected:NO animated:YES]; - } else { - [self.pointerStyleTouchscreenCell setAccessoryType:UITableViewCellAccessoryNone]; - [self.pointerStyleTrackpadCell setAccessoryType:UITableViewCellAccessoryCheckmark]; - [self.pointerStyleTrackpadCell setSelected:NO animated:YES]; +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + if ([tableView cellForRowAtIndexPath:indexPath] == self.openSettingsCell) { + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] + options:@{} + completionHandler:nil]; + [tableView deselectRowAtIndexPath:indexPath animated:YES]; } } -- (void)setInputDirect:(BOOL)inputDirect { - _inputDirect = inputDirect; - self.configuration.inputDirect = inputDirect; - if (inputDirect) { - [self.inputReceiverDirectCell setAccessoryType:UITableViewCellAccessoryCheckmark]; - [self.inputReceiverServerCell setAccessoryType:UITableViewCellAccessoryNone]; - [self.inputReceiverDirectCell setSelected:NO animated:YES]; - } else { - [self.inputReceiverDirectCell setAccessoryType:UITableViewCellAccessoryNone]; - [self.inputReceiverServerCell setAccessoryType:UITableViewCellAccessoryCheckmark]; - [self.inputReceiverServerCell setSelected:NO animated:YES]; - } -} +#pragma mark - Event handlers -#pragma mark - Table delegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if ([tableView cellForRowAtIndexPath:indexPath] == self.pointerStyleTouchscreenCell) { - self.inputTouchscreenMode = YES; - } - if ([tableView cellForRowAtIndexPath:indexPath] == self.pointerStyleTrackpadCell) { - self.inputTouchscreenMode = NO; - } - if ([tableView cellForRowAtIndexPath:indexPath] == self.inputReceiverDirectCell) { - self.inputDirect = YES; - } - if ([tableView cellForRowAtIndexPath:indexPath] == self.inputReceiverServerCell) { - self.inputDirect = NO; - } +- (IBAction)legacyModeChanged:(UISwitch *)sender { + self.configuration.inputLegacy = sender.on; } @end diff --git a/Managers/UTMQemuSystem.m b/Managers/UTMQemuSystem.m index e57402362..07997b251 100644 --- a/Managers/UTMQemuSystem.m +++ b/Managers/UTMQemuSystem.m @@ -176,7 +176,7 @@ - (void)argsFromConfiguration { [self pushArgv:@"none"]; } // usb input if not legacy - if (1) { // TODO: implement legacy mode + if (!self.configuration.inputLegacy) { [self pushArgv:@"-device"]; [self pushArgv:@"usb-ehci"]; [self pushArgv:@"-device"]; diff --git a/UTM/Base.lproj/Main.storyboard b/UTM/Base.lproj/Main.storyboard index f9400ca06..8524e3253 100644 --- a/UTM/Base.lproj/Main.storyboard +++ b/UTM/Base.lproj/Main.storyboard @@ -3056,74 +3056,50 @@ - - Touchscreen: press anywhere on the screen to click there. Trackpad: move cursor by swipping on the screen and click with a tap. Right click with a two finger tap. + - + - - - - - - - - - - - - - + + - + + + + + + + - - Direct: input sent to emulator directly. Can appear to be out of sync with display. Server: input sent to display server. Can have more latency but appear more responsive. + - - + + - - - - - - - - - - - - + -