Skip to content

Commit

Permalink
Add external extended display implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
conath committed Oct 14, 2020
1 parent f84be27 commit b4469a3
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 29 deletions.
1 change: 1 addition & 0 deletions CocoaSpice/CSDisplayMetal.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
- (id)initWithSession:(nonnull SpiceSession *)session channelID:(NSInteger)channelID;
- (void)updateVisibleAreaWithRect:(CGRect)rect;
- (void)requestResolution:(CGRect)bounds;
- (void)requestResolution:(CGRect)bounds monitorID:(NSInteger)monitorID;

@end

Expand Down
9 changes: 7 additions & 2 deletions CocoaSpice/CSDisplayMetal.m
Original file line number Diff line number Diff line change
Expand Up @@ -408,13 +408,18 @@ - (BOOL)visible {
}

- (void)requestResolution:(CGRect)bounds {
[self requestResolution:bounds monitorID:self.monitorID];
}

- (void)requestResolution:(CGRect)bounds monitorID:(NSInteger)monitorID {

if (!_main) {
UTMLog(@"ignoring change resolution because main channel not found");
return;
}
spice_main_channel_update_display_enabled(_main, (int)self.monitorID, TRUE, FALSE);
spice_main_channel_update_display_enabled(_main, (int)monitorID, TRUE, FALSE);
spice_main_channel_update_display(_main,
(int)self.monitorID,
(int)monitorID,
bounds.origin.x,
bounds.origin.y,
bounds.size.width,
Expand Down
1 change: 1 addition & 0 deletions Managers/UTMSpiceIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithConfiguration: (UTMConfiguration*) configuration port:(NSInteger)port NS_DESIGNATED_INITIALIZER;
- (void)changeSharedDirectory:(NSURL *)url;
- (CSConnection*)getSpiceConnection;

@end

Expand Down
7 changes: 7 additions & 0 deletions Managers/UTMSpiceIO.m
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ - (void)restoreViewState:(UTMViewState *)viewState {
self.primaryDisplay.viewportScale = viewState.displayScale;
}

- (CSConnection *)getSpiceConnection {
return _spiceConnection;
}

#pragma mark - CSConnectionDelegate

- (void)spiceConnected:(CSConnection *)connection {
Expand Down Expand Up @@ -193,6 +197,9 @@ - (void)spiceDisplayCreated:(CSConnection *)connection display:(CSDisplayMetal *
self.connectionCallback(YES, nil);
self.connectionCallback = nil;
}
} else {
// TODO external
[[NSNotificationCenter defaultCenter] postNotificationName:@"externalDisplayAdded" object:nil userInfo:@{@"display":display, @"input":input}];
}
}

Expand Down
2 changes: 1 addition & 1 deletion Platform/iOS/Display/VMDisplayMetalViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ - (void)viewDidLoad {
[self initPencilInteraction];
}
// External screen
_externalController = [[ExternalScreenController alloc] initWithVmViewController:self metalView: self.mtkView sourceScreen: self.vmDisplay sourceCursor: self.vmInput];
_externalController = [[ExternalScreenController alloc] initWithVmViewController:self metalView: self.mtkView];
}

- (void)viewDidAppear:(BOOL)animated {
Expand Down
31 changes: 26 additions & 5 deletions Platform/iOS/Display/VMExternalDisplayMetalViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,21 @@

import UIKit

class VMExternalDisplayMetalViewController: VMDisplayViewController {
class VMExternalDisplayMetalViewController: UIViewController {
private let mtkView = MTKView()

var renderer: UTMRenderer!
var screenSize: CGSize!

override func loadView() {
super.loadView()
NotificationCenter.default.addObserver(self, selector: #selector(handleDisplayAdded), name: .init(rawValue: "externalDisplayAdded"), object: nil)
}

private var renderer: UTMRenderer!
var sourceScreen: UTMRenderSource?
var sourceCursor: UTMRenderSource?

override func viewDidLoad() {
// don't call VMDisplayViewController.viewDidLoad because that inits the accesory view
(self as UIViewController).viewDidLoad()
super.viewDidLoad()

view.addSubview(mtkView)
mtkView.bindFrameToSuperviewBounds()
Expand All @@ -37,8 +41,25 @@ class VMExternalDisplayMetalViewController: VMDisplayViewController {
UTM.logger.critical("Metal is not supported on this device")
return;
}
}

@objc func handleDisplayAdded(_ notification: Notification) {
print("Yippie kay jay Schweinebacke")
guard let userInfo = notification.userInfo,
let display = userInfo["display"] as? CSDisplayMetal,
let input = userInfo["input"] as? CSInput else { return }
sourceScreen = display
sourceCursor = input

renderer = UTMRenderer(metalKitView: mtkView)
renderer.sourceScreen = sourceScreen
renderer.sourceCursor = sourceCursor
mtkView.delegate = renderer
renderer.mtkView(mtkView, drawableSizeWillChange: screenSize)
}

override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
}
32 changes: 11 additions & 21 deletions Platform/iOS/ExternalScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,10 @@ import UIKit
private var externalWindow: UIWindow?
private weak var externalVC: UIViewController?

private var sourceScreen: UTMRenderSource?
private var sourceCursor: UTMRenderSource?

@objc init(vmViewController: VMDisplayMetalViewController, metalView: MTKView, sourceScreen: UTMRenderSource?, sourceCursor: UTMRenderSource?) {
@objc init(vmViewController: VMDisplayMetalViewController, metalView: MTKView) {
super.init()
self.vmViewController = vmViewController
self.metalView = metalView
self.sourceScreen = sourceScreen
self.sourceCursor = sourceCursor

// Listen for external screen events
NotificationCenter.default.addObserver(forName: UIScreen.didConnectNotification, object: nil, queue: nil) { [weak self] notification in
Expand All @@ -56,7 +51,7 @@ import UIKit
if let window = self.externalWindow, window.screen == oldScreen {
if let extVC = self.externalVC as? VMExternalDisplayMetalViewController {
// discard external metal view
extVC.renderer = nil // ?
extVC.dismiss(animated: false, completion: nil)
} else if let extVC = self.externalVC {
extVC.view.removeFromSuperview()
metalView.removeFromSuperview()
Expand Down Expand Up @@ -104,11 +99,9 @@ import UIKit
let newWindow = UIWindow(frame: screenFrame)
externalWindow = newWindow
newWindow.screen = newScreen

metalView.removeFromSuperview()

makeExternalOnlyVC(newWindow: newWindow)
// makeExternalDuplicateVC(newWindow: newWindow)
makeExtendedDisplayVC(newWindow: newWindow)
// makeExternalOnlyVC(newWindow: newWindow)

newWindow.isHidden = false

Expand All @@ -123,23 +116,20 @@ import UIKit
}
}

private func makeExternalDuplicateVC(newWindow: UIWindow) {
private func makeExtendedDisplayVC(newWindow: UIWindow) {
let extVC = VMExternalDisplayMetalViewController()
extVC.screenSize = newWindow.bounds.size
extVC.renderer = (metalView!.delegate as! UTMRenderer)
extVC.sourceScreen = sourceScreen
extVC.sourceCursor = sourceCursor
newWindow.rootViewController = extVC
extVC.loadView()
DispatchQueue.main.async {
let renderer = (self.metalView!.delegate as! UTMRenderer)
renderer.mtkView(self.metalView!, drawableSizeWillChange: self.externalWindow!.bounds.size)
self.metalView!.drawableSize = newWindow.bounds.size
}
newWindow.rootViewController = extVC
self.externalVC = extVC
/// request `CSDisplay` to create a virtual display with the external window bounds
guard let mainDisplay = vmViewController.vmDisplay else { return }
let newMonitorID = mainDisplay.monitorID + 1 // TODO more than 1 external?
mainDisplay.requestResolution(newWindow.bounds, monitorID: newMonitorID)
}

private func makeExternalOnlyVC(newWindow: UIWindow) {
metalView.removeFromSuperview()
let externalVC = UIViewController()
newWindow.rootViewController = externalVC
externalVC.view.addSubview(metalView)
Expand Down

0 comments on commit b4469a3

Please sign in to comment.