So I'm trying to show a window overlay over entire screen (even dock and menu bar) capturing all input events, and after a Timer defined x seconds, hide it. I know this is possible because there's an app in AppStore doing that.
I've found two approaches: First:
let windowLevel = CGShieldingWindowLevel();
let windowRect = NSScreen.main?.frame
var overlayWindow = NSWindow(contentRect: windowRect!, styleMask: NSWindow.StyleMask.borderless, backing: NSWindow.BackingStoreType.buffered, defer: false, screen: NSScreen.screens[0])
overlayWindow.level = NSWindow.Level(rawValue: NSWindow.Level.RawValue(windowLevel))
overlayWindow.backgroundColor = .black
overlayWindow.alphaValue = 0.4
overlayWindow.makeKeyAndOrderFront(nil)
overlayWindow.makeMain()
Second: Using storyboards
let window = FullScreenWindowController(windowNibName: NSNib.Name(rawValue: "FullScreenWindow"))
self.application.runModal(for: self.window.window!)
The first solution causes this log to appear:
Assertion failure in -[NSWindow _changeJustMain], /Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1504.83.101/AppKit.subproj/NSWindow.m:14861
Invalid parameter not satisfying: [self canBecomeMainWindow]
And also I'm unable to run a timer while the modal is being presented. The modal blocks all events and the timer loop can't happen. I saw some approaches with NSRunner looper... but I'm not sure this is still possible with current SDK version.
As for the second solution, I can't restore the initial app state, I mean hide the overlay after showing it. The other drawback of this solution is that the dock is still visible and interaction is possible.
Would appreciate some suggestions as I'm quite new to MacOS dev.
Got it solved by setting window level to CGShieldingWindowLevel() in the second approach. Not sure though if this is correct(Apple permits) and can be used (docs say shouldn't)...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With