Wake iso's display for hands calls while it sleeps
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import CoreGraphics
|
||||
import IOKit.pwr_mgt
|
||||
import ScreenCaptureKit
|
||||
|
||||
func displayAsleep() -> Bool {
|
||||
let id = CGMainDisplayID()
|
||||
return CGDisplayIsAsleep(id) != 0 || CGDisplayBounds(id).width == 0
|
||||
}
|
||||
|
||||
func displayCapturable() async -> Bool {
|
||||
if displayAsleep() {
|
||||
return false
|
||||
}
|
||||
// Without Screen Recording this throws; stop waiting so tools that don't capture still run.
|
||||
guard let content = try? await SCShareableContent.excludingDesktopWindows(false, onScreenWindowsOnly: true) else {
|
||||
return true
|
||||
}
|
||||
return content.displays.contains(where: { $0.displayID == CGMainDisplayID() })
|
||||
}
|
||||
|
||||
func withDisplayAwake<T>(_ body: () async throws -> T) async throws -> T {
|
||||
var hold = IOPMAssertionID(0)
|
||||
IOPMAssertionCreateWithName(kIOPMAssertionTypePreventUserIdleDisplaySleep as CFString, IOPMAssertionLevel(kIOPMAssertionLevelOn), "byre-hands" as CFString, &hold)
|
||||
defer {
|
||||
IOPMAssertionRelease(hold)
|
||||
}
|
||||
if displayAsleep() {
|
||||
var wake = IOPMAssertionID(0)
|
||||
IOPMAssertionDeclareUserActivity("byre-hands" as CFString, kIOPMUserActiveLocal, &wake)
|
||||
defer {
|
||||
IOPMAssertionRelease(wake)
|
||||
}
|
||||
let deadline = ContinuousClock.now + .seconds(10)
|
||||
while !(await displayCapturable()) {
|
||||
if ContinuousClock.now > deadline {
|
||||
throw ToolError("the display didn't wake within 10s")
|
||||
}
|
||||
try await Task.sleep(for: .milliseconds(100))
|
||||
}
|
||||
}
|
||||
return try await body()
|
||||
}
|
||||
@@ -101,7 +101,7 @@ struct Server {
|
||||
return ["content": [Content.text("unknown tool: \(name)").json], "isError": true]
|
||||
}
|
||||
do {
|
||||
let content = try await tool.run(args)
|
||||
let content = try await withDisplayAwake { try await tool.run(args) }
|
||||
return ["content": content.map { $0.json }]
|
||||
} catch let e as ToolError {
|
||||
return ["content": [Content.text(e.message).json], "isError": true]
|
||||
|
||||
Reference in New Issue
Block a user