CocoaSpice: updated backend

This commit is contained in:
osy 2022-05-27 12:06:29 -07:00
parent 489b12920e
commit 2224ffadba
14 changed files with 121 additions and 66 deletions

View File

@ -32,7 +32,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface UTMSpiceIO : NSObject<CSConnectionDelegate>
@property (nonatomic, readonly, nonnull) UTMQemuConfiguration* configuration;
@property (nonatomic, readonly, nullable) CSDisplayMetal *primaryDisplay;
@property (nonatomic, readonly, nullable) CSDisplay *primaryDisplay;
@property (nonatomic, readonly, nullable) CSInput *primaryInput;
@property (nonatomic, readonly, nullable) CSPort *primarySerial;
#if !defined(WITH_QEMU_TCI)

View File

@ -29,7 +29,7 @@ extern NSString *const kUTMErrorDomain;
@interface UTMSpiceIO ()
@property (nonatomic, readwrite, nullable) CSDisplayMetal *primaryDisplay;
@property (nonatomic, readwrite, nullable) CSDisplay *primaryDisplay;
@property (nonatomic, readwrite, nullable) CSInput *primaryInput;
@property (nonatomic, readwrite, nullable) CSPort *primarySerial;
#if !defined(WITH_QEMU_TCI)
@ -147,14 +147,26 @@ extern NSString *const kUTMErrorDomain;
- (void)spiceConnected:(CSConnection *)connection {
NSAssert(connection == self.spiceConnection, @"Unknown connection");
self.isConnected = YES;
self.primaryInput = connection.input;
[self.delegate spiceDidChangeInput:connection.input];
#if !defined(WITH_QEMU_TCI)
self.primaryUsbManager = connection.usbManager;
[self.delegate spiceDidChangeUsbManager:connection.usbManager];
#endif
}
- (void)spiceInputAvailable:(CSConnection *)connection input:(CSInput *)input {
if (self.primaryInput == nil) {
self.primaryInput = input;
[self.delegate spiceDidCreateInput:input];
}
}
- (void)spiceInputUnavailable:(CSConnection *)connection input:(CSInput *)input {
if (self.primaryInput == input) {
self.primaryInput = nil;
[self.delegate spiceDidDestroyInput:input];
}
}
- (void)spiceDisconnected:(CSConnection *)connection {
NSAssert(connection == self.spiceConnection, @"Unknown connection");
self.isConnected = NO;
@ -171,15 +183,17 @@ extern NSString *const kUTMErrorDomain;
});
}
- (void)spiceDisplayCreated:(CSConnection *)connection display:(CSDisplayMetal *)display {
- (void)spiceDisplayCreatedOrUpdated:(CSConnection *)connection display:(CSDisplay *)display {
NSAssert(connection == self.spiceConnection, @"Unknown connection");
[self.delegate spiceDidCreateDisplay:display];
if (display.isPrimaryDisplay) {
if (self.primaryDisplay == display) {
[self.delegate spiceDidChangeDisplay:display];
} else if (display.isPrimaryDisplay) {
self.primaryDisplay = display;
[self.delegate spiceDidCreateDisplay:display];
}
}
- (void)spiceDisplayDestroyed:(CSConnection *)connection display:(CSDisplayMetal *)display {
- (void)spiceDisplayDestroyed:(CSConnection *)connection display:(CSDisplay *)display {
NSAssert(connection == self.spiceConnection, @"Unknown connection");
[self.delegate spiceDidDestroyDisplay:display];
}
@ -248,16 +262,11 @@ extern NSString *const kUTMErrorDomain;
_delegate = delegate;
// make sure to send initial data
if (self.primaryInput) {
[self.delegate spiceDidChangeInput:self.primaryInput];
[self.delegate spiceDidCreateInput:self.primaryInput];
}
if (self.primaryDisplay) {
[self.delegate spiceDidCreateDisplay:self.primaryDisplay];
}
for (CSDisplayMetal *display in self.spiceConnection.monitors) {
if (display != self.primaryDisplay) {
[self.delegate spiceDidCreateDisplay:display];
}
}
if (self.primarySerial) {
[self.delegate spiceDidCreateSerial:self.primarySerial];
}

View File

@ -16,7 +16,7 @@
#import <Foundation/Foundation.h>
@class CSDisplayMetal;
@class CSDisplay;
@class CSInput;
@class CSPort;
@class CSUSBManager;
@ -25,13 +25,15 @@ NS_ASSUME_NONNULL_BEGIN
@protocol UTMSpiceIODelegate<NSObject>
- (void)spiceDidChangeInput:(CSInput *)input;
- (void)spiceDidCreateDisplay:(CSDisplayMetal *)display;
- (void)spiceDidDestroyDisplay:(CSDisplayMetal *)display;
- (void)spiceDidCreateSerial:(CSPort *)serial;
- (void)spiceDidDestroySerial:(CSPort *)serial;
- (void)spiceDidCreateInput:(CSInput *)input NS_SWIFT_NAME(spiceDidCreateInput(_:));
- (void)spiceDidDestroyInput:(CSInput *)input NS_SWIFT_NAME(spiceDidDestroyInput(_:));
- (void)spiceDidCreateDisplay:(CSDisplay *)display NS_SWIFT_NAME(spiceDidCreateDisplay(_:));
- (void)spiceDidDestroyDisplay:(CSDisplay *)display NS_SWIFT_NAME(spiceDidDestroyDisplay(_:));
- (void)spiceDidChangeDisplay:(CSDisplay *)display NS_SWIFT_NAME(spiceDidChangeDisplay(_:));
- (void)spiceDidCreateSerial:(CSPort *)serial NS_SWIFT_NAME(spiceDidCreateSerial(_:));
- (void)spiceDidDestroySerial:(CSPort *)serial NS_SWIFT_NAME(spiceDidDestroySerial(_:));
#if !defined(WITH_QEMU_TCI)
- (void)spiceDidChangeUsbManager:(CSUSBManager *)usbManager;
- (void)spiceDidChangeUsbManager:(nullable CSUSBManager *)usbManager NS_SWIFT_NAME(spiceDidChangeUsbManager(_:));
#endif
@optional

View File

@ -16,7 +16,7 @@
@protocol UTMConfigurable;
@class UTMVirtualMachine;
@class CSDisplayMetal;
@class CSDisplay;
@class CSInput;
NS_ASSUME_NONNULL_BEGIN

View File

@ -16,7 +16,7 @@
#import "VMCursor.h"
#import "VMDisplayMetalViewController+Touch.h"
#import "CSDisplayMetal.h"
#import "CSDisplay.h"
@interface VMCursor ()
@ -64,8 +64,8 @@
- (CGRect)bounds {
CGRect bounds = CGRectZero;
bounds.size.width = MAX(1, _controller.vmDisplay.cursorSize.width);
bounds.size.height = MAX(1, _controller.vmDisplay.cursorSize.height);
bounds.size.width = MAX(1, _controller.vmDisplay.cursor.cursorSize.width);
bounds.size.height = MAX(1, _controller.vmDisplay.cursor.cursorSize.height);
return bounds;
}

View File

@ -19,7 +19,7 @@
#import "VMScroll.h"
#import "VMDisplayMetalViewController+Gamepad.h"
#import "VMDisplayMetalViewController+Touch.h"
#import "CSDisplayMetal.h"
#import "CSDisplay.h"
#import "UTMQemuConfiguration.h"
#import "UTMQemuConfiguration+Constants.h"
#import "UTMLogging.h"

View File

@ -20,7 +20,7 @@
#import "VMDisplayMetalViewController+Touch.h"
#import "VMDisplayMetalViewController+Pointer.h"
#import "VMCursor.h"
#import "CSDisplayMetal.h"
#import "CSDisplay.h"
#import "VMScroll.h"
#import "UTMQemuVirtualMachine.h"
#import "UTMQemuVirtualMachine+SPICE.h"

View File

@ -20,7 +20,7 @@
#import "VMDisplayMetalViewController+Pencil.h"
#import "VMCursor.h"
#import "VMScroll.h"
#import "CSDisplayMetal.h"
#import "CSDisplay.h"
#import "UTMQemuConfiguration.h"
#import "UTMQemuConfiguration+Miscellaneous.h"
#import "UTMSpiceIO.h"
@ -353,7 +353,7 @@ static CGFloat CGPointToPixel(CGFloat point) {
translated = [self clipCursorToDisplay:translated];
if (!self.vmInput.serverModeCursor) {
[self.vmInput sendMousePosition:self.mouseButtonDown absolutePoint:translated];
[self.vmDisplay forceCursorPosition:translated]; // required to show cursor on screen
[self.vmDisplay.cursor moveTo:translated]; // required to show cursor on screen
} else {
UTMLog(@"Warning: ignored mouse set (%f, %f) while mouse is in server mode", translated.x, translated.y);
}
@ -625,7 +625,7 @@ static CGFloat CGPointToPixel(CGFloat point) {
- (BOOL)switchMouseType:(VMMouseType)type {
BOOL shouldHideCursor = (type == VMMouseTypeAbsoluteHideCursor);
BOOL shouldUseServerMouse = (type == VMMouseTypeRelative);
self.vmDisplay.inhibitCursor = shouldHideCursor;
self.vmDisplay.cursor.isInhibited = shouldHideCursor;
if (shouldUseServerMouse != self.vmInput.serverModeCursor) {
UTMLog(@"Switching mouse mode to server:%d for type:%ld", shouldUseServerMouse, type);
[self.vm requestInputTablet:!shouldUseServerMouse];

View File

@ -64,7 +64,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) IBOutlet VMKeyboardView *keyboardView;
@property (weak, nonatomic) CSInput *vmInput;
@property (weak, nonatomic) CSDisplayMetal *vmDisplay;
@property (weak, nonatomic) CSDisplay *vmDisplay;
@property (nonatomic, readonly) BOOL serverModeCursor;

View File

@ -26,7 +26,7 @@
#import "UTMQemuConfiguration.h"
#import "UTMQemuConfiguration+Display.h"
#import "UTMLogging.h"
#import "CSDisplayMetal.h"
#import "CSDisplay.h"
#import "UTM-Swift.h"
@import CocoaSpiceRenderer;
@ -200,12 +200,20 @@
#pragma mark - SPICE IO Delegates
- (void)spiceDidChangeInput:(CSInput *)input {
- (void)spiceDidCreateInput:(CSInput *)input {
if (self.vmInput == nil) {
self.vmInput = input;
}
}
- (void)spiceDidCreateDisplay:(CSDisplayMetal *)display {
if (display.isPrimaryDisplay) {
- (void)spiceDidDestroyInput:(CSInput *)input {
if (self.vmInput == input) {
self.vmInput = nil;
}
}
- (void)spiceDidCreateDisplay:(CSDisplay *)display {
if (self.vmDisplay == nil && display.isPrimaryDisplay) {
self.vmDisplay = display;
_renderer.source = display;
// restore last size
@ -224,8 +232,17 @@
}
}
- (void)spiceDidDestroyDisplay:(CSDisplayMetal *)display {
// TODO: implement something here
- (void)spiceDidDestroyDisplay:(CSDisplay *)display {
if (self.vmDisplay == display) {
self.vmDisplay = nil;
_renderer.source = nil;
}
}
- (void)spiceDidChangeDisplay:(CSDisplay *)display {
if (display == self.vmDisplay) {
}
}
@end

View File

@ -99,13 +99,19 @@
#pragma mark - SPICE IO Delegates
- (void)spiceDidChangeInput:(CSInput *)input {
- (void)spiceDidCreateInput:(CSInput *)input {
}
- (void)spiceDidCreateDisplay:(CSDisplayMetal *)display {
- (void)spiceDidDestroyInput:(CSInput *)input {
}
- (void)spiceDidDestroyDisplay:(CSDisplayMetal *)display {
- (void)spiceDidCreateDisplay:(CSDisplay *)display {
}
- (void)spiceDidChangeDisplay:(CSDisplay *)display {
}
- (void)spiceDidDestroyDisplay:(CSDisplay *)display {
}
- (void)spiceDidCreateSerial:(CSPort *)serial {

View File

@ -20,10 +20,9 @@ class VMDisplayMetalWindowController: VMDisplayQemuWindowController {
var metalView: VMMetalView!
var renderer: CSRenderer?
private weak var vmDisplay: CSDisplayMetal?
private weak var vmDisplay: CSDisplay?
private weak var vmInput: CSInput?
private var displaySizeObserver: NSKeyValueObservation?
private var displaySize: CGSize = .zero
private var isDisplaySizeDynamic: Bool = false
private var isFullScreen: Bool = false
@ -77,10 +76,6 @@ class VMDisplayMetalWindowController: VMDisplayQemuWindowController {
override func enterLive() {
metalView.isHidden = false
screenshotView.isHidden = true
displaySizeObserver = observe(\.vmDisplay!.displaySize, options: [.initial, .new]) { (_, change) in
guard let size = change.newValue else { return }
self.displaySizeDidChange(size: size)
}
if vmQemuConfig!.shareClipboardEnabled {
UTMPasteboard.general.requestPollingMode(forHashable: self) // start clipboard polling
}
@ -121,7 +116,6 @@ class VMDisplayMetalWindowController: VMDisplayQemuWindowController {
self.globalEventMonitor = nil
}
releaseMouse()
displaySizeObserver = nil
super.enterSuspended(isBusy: busy)
}
@ -132,19 +126,36 @@ class VMDisplayMetalWindowController: VMDisplayQemuWindowController {
// MARK: - SPICE IO
extension VMDisplayMetalWindowController {
override func spiceDidChange(_ input: CSInput) {
override func spiceDidCreateInput(_ input: CSInput) {
if vmInput == nil {
vmInput = input
}
}
override func spiceDidCreateDisplay(_ display: CSDisplayMetal) {
if display.isPrimaryDisplay {
override func spiceDidDestroyInput(_ input: CSInput) {
if vmInput == input {
vmInput = nil
}
}
override func spiceDidCreateDisplay(_ display: CSDisplay) {
if vmDisplay == nil && display.isPrimaryDisplay {
vmDisplay = display
renderer!.source = vmDisplay
renderer!.source = display
}
}
override func spiceDidDestroyDisplay(_ display: CSDisplayMetal) {
//TODO: implement something here
override func spiceDidDestroyDisplay(_ display: CSDisplay) {
if vmDisplay == display {
vmDisplay = nil
renderer!.source = nil
}
}
override func spiceDidChangeDisplay(_ display: CSDisplay) {
if vmDisplay == display {
displaySizeDidChange(size: display.displaySize)
}
}
override func spiceDynamicResolutionSupportDidChange(_ supported: Bool) {
@ -345,7 +356,7 @@ extension VMDisplayMetalWindowController: VMMetalViewInputDelegate {
let point = CGPoint(x: newX, y: newY)
logger.trace("move cursor: cocoa (\(absolutePoint.x), \(absolutePoint.y)), native (\(newX), \(newY))")
vmInput.sendMousePosition(button, absolutePoint: point)
vmDisplay?.forceCursorPosition(point) // required to show cursor on screen
vmDisplay?.cursor?.move(to: point) // required to show cursor on screen
}
func mouseMove(relativePoint: CGPoint, button: CSInputButton) {

View File

@ -208,26 +208,36 @@ extension VMDisplayQemuWindowController {
// MARK: - SPICE base implementation
extension VMDisplayQemuWindowController: UTMSpiceIODelegate {
func spiceDidChange(_ input: CSInput) {
func spiceDidCreateInput(_ input: CSInput) {
// Implemented in subclass
}
func spiceDidCreateDisplay(_ display: CSDisplayMetal) {
func spiceDidDestroyInput(_ input: CSInput) {
// Implemented in subclass
}
func spiceDidDestroyDisplay(_ display: CSDisplayMetal) {
func spiceDidCreateDisplay(_ display: CSDisplay) {
// Implemented in subclass
}
func spiceDidChange(_ usbManager: CSUSBManager) {
func spiceDidChangeDisplay(_ display: CSDisplay) {
// Implemented in subclass
}
func spiceDidDestroyDisplay(_ display: CSDisplay) {
// Implemented in subclass
}
func spiceDidChangeUsbManager(_ usbManager: CSUSBManager?) {
if usbManager != vmUsbManager {
connectedUsbDevices.removeAll()
allUsbDevices.removeAll()
vmUsbManager = usbManager
if let usbManager = usbManager {
usbManager.delegate = self
}
}
}
func spiceDynamicResolutionSupportDidChange(_ supported: Bool) {
// Implemented in subclass

View File

@ -15,7 +15,7 @@
"repositoryURL": "https://github.com/utmapp/CocoaSpice.git",
"state": {
"branch": "main",
"revision": "6a210bc6dd50d12bd57f990bd4d062d0fd93d529",
"revision": "5070355c1ca5706c50bd74e8d65f89debd7bf8a0",
"version": null
}
},