Fullscreen NSWindow on Secondary Monitor - Swift

2019-08-18 06:20发布

问题:

I have seen many posts on this in Obj C. Not too many in swift, and I just can't get it to work. I want to be able to make a window fullscreen on a specific NSScreen. The 'ToggleFullscreen' method isn't the best way because there aren't many options (for external displays). I tried:

    // screen is my variable already set
    outputWindow!.window!.setFrame(screen.frame, display: true, animate: true)
    outputWindow!.window!.styleMask = NSFullScreenWindowMask
    outputWindow!.window!.level = Int(CGShieldingWindowLevel())

    // the above one doesn't make it fullscreen.
    // it has a title bar and shows the menu on the screen. 



    // then i tried....
    fullscreenWindow = NSWindow(contentRect: screen.frame, styleMask:NSBorderlessWindowMask, backing: NSBackingStoreType.Buffered, defer: false, screen: screen)
    fullscreenWindow.level = Int(CGShieldingWindowLevel())
    fullscreenWindow.makeKeyAndOrderFront(nil)

    //that one works on my main display (somewhat). and does nothing on externals. 

One thing I noticed with making my own fullscreen is that I get stuck into it. It's not like the OS X fullscreen where you can press esc to escape it. Are there any tricks to this? Thanks

回答1:

I struggled with getting stuck on fullscreen as well. The reason behind that is using NSBorderlessWindowMask prevents the window from becoming key regardless of sending the makeKeyAndOrderFront: or makeKeyWindow messages to it. In Objective-C, the solution was to implement canBecomeKeyWindow in the subclassed NSWindow.

- (BOOL)canBecomeKeyWindow {
     return YES;
}

Now it receives key events after going full screen as well.



回答2:

This is a pseudo answer:

[in a inherited class of NSWondowController]

var fullscreen:Bool {
    set {
        if newValue == true {

            if fullscreen == true {
                return
            }

            frameOrig = self.window?.frame
            self.window?.setFrame((NSScreen.main()?.frame)!, display: true)
        }
        else {
            self.window?.setFrame(frameOrig!, display: true)
        }
    }
    get {
        return self.window?.frame == NSScreen.main()?.frame
    }
}

I also trapped key events on both the calling-window and fullscreen window and point them to the above function so that toggling is possible. Like so:

[in some viewcontroller]:

override func keyUp(with event: NSEvent) {
    switch event.keyCode {
    case 53:
        debugPrint("ESC - randomviewcontroller")
        (randomView.window?.windowController as! RandomWindowController).fullscreen = !(RandomView.window?.windowController as! RandomWindowController).fullscreen;
        break
    default:
        super.keyUp(with: event)
    }
}

I think the above can be done much better & smarter... (picked up Swift a month ago...) but as the saying goes: "It worked on my computer!"

Hope it helps.