CocoaSpice: updated backend
This commit is contained in:
parent
489b12920e
commit
2224ffadba
|
@ -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)
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
@protocol UTMConfigurable;
|
||||
@class UTMVirtualMachine;
|
||||
@class CSDisplayMetal;
|
||||
@class CSDisplay;
|
||||
@class CSInput;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
"repositoryURL": "https://github.com/utmapp/CocoaSpice.git",
|
||||
"state": {
|
||||
"branch": "main",
|
||||
"revision": "6a210bc6dd50d12bd57f990bd4d062d0fd93d529",
|
||||
"revision": "5070355c1ca5706c50bd74e8d65f89debd7bf8a0",
|
||||
"version": null
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue