Skip to content

Commit

Permalink
Introduce --capture-system-keys flag (#650)
Browse files Browse the repository at this point in the history
To allow guest to capture things like Cmd+Tab.

Fixes #636
  • Loading branch information
fkorotkov authored Nov 8, 2023
1 parent 43e74ab commit c75009e
Showing 1 changed file with 15 additions and 7 deletions.
22 changes: 15 additions & 7 deletions Sources/tart/Commands/Run.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ struct Run: AsyncParsableCommand {
@Flag(help: ArgumentHelp("Disables audio and entropy devices and switches to only Mac-specific input devices.", discussion: "Useful for running a VM that can be suspended via \"tart suspend\"."))
var suspendable: Bool = false

@Flag(help: ArgumentHelp("Whether system hot keys should be sent to the guest instead of the host",
discussion: "If enabled then system hot keys like Cmd+Tab will be sent to the guest instead of the host."))
var captureSystemKeys: Bool = false

mutating func validate() throws {
if vnc && vncExperimental {
throw ValidationError("--vnc and --vnc-experimental are mutually exclusive")
Expand All @@ -121,6 +125,10 @@ struct Run: AsyncParsableCommand {
throw ValidationError("--graphics and --no-graphics are mutually exclusive")
}

if (noGraphics || vnc || vncExperimental) && captureSystemKeys {
throw ValidationError("--captures-system-keys can only be used with the default VM view")
}

let localStorage = VMStorageLocal()
let vmDir = try localStorage.open(name)
if try vmDir.state() == "suspended" {
Expand Down Expand Up @@ -306,7 +314,7 @@ struct Run: AsyncParsableCommand {
if noGraphics || useVNCWithoutGraphics {
dispatchMain()
} else {
runUI(suspendable)
runUI(suspendable, captureSystemKeys)
}
}

Expand Down Expand Up @@ -467,7 +475,7 @@ struct Run: AsyncParsableCommand {
return [device]
}

private func runUI(_ suspendable: Bool) {
private func runUI(_ suspendable: Bool, _ captureSystemKeys: Bool) {
let nsApp = NSApplication.shared
nsApp.setActivationPolicy(.regular)
nsApp.activate(ignoringOtherApps: true)
Expand All @@ -476,13 +484,14 @@ struct Run: AsyncParsableCommand {

struct MainApp: App {
static var disappearSignal: Int32 = SIGINT
static var capturesSystemKeys: Bool = false

@NSApplicationDelegateAdaptor private var appDelegate: MinimalMenuAppDelegate

var body: some Scene {
WindowGroup(vm!.name) {
Group {
VMView(vm: vm!).onAppear {
VMView(vm: vm!, capturesSystemKeys: MainApp.capturesSystemKeys).onAppear {
NSWindow.allowsAutomaticWindowTabbing = false
}.onDisappear {
let ret = kill(getpid(), MainApp.disappearSignal)
Expand Down Expand Up @@ -532,6 +541,7 @@ struct Run: AsyncParsableCommand {
}

MainApp.disappearSignal = suspendable ? SIGUSR1 : SIGINT
MainApp.capturesSystemKeys = captureSystemKeys
MainApp.main()
}
}
Expand Down Expand Up @@ -581,14 +591,12 @@ struct VMView: NSViewRepresentable {
typealias NSViewType = VZVirtualMachineView

@ObservedObject var vm: VM
var capturesSystemKeys: Bool

func makeNSView(context: Context) -> NSViewType {
let machineView = VZVirtualMachineView()

// Do not capture system keys so that shortcuts like
// Shift-Command-4 + Space (capture a screenshot of window)
// work on the host instead of the guest
machineView.capturesSystemKeys = false
machineView.capturesSystemKeys = capturesSystemKeys

// Enable automatic display reconfiguration
// for guests that support it
Expand Down

0 comments on commit c75009e

Please sign in to comment.