Federico Curzel
Federico Curzel

Reputation: 68

Accessing NSWindow-like properties in Catalyst macOS app

I am thinking about porting my macOS app to Catalyst.

My app shows a transparent window (no title bar, clear background) on top of all other apps windows (dock included). To do that, in the non-catalyst code I use:

window.isOpaque = false
window.hasShadow = false
window.backgroundColor = .clear
window.styleMask = .borderless
window.isMovableByWindowBackground = true
window.level = .statusBar

Using UIKit, I was only able to remove the toolbar so far:

window.titleBar.titleVisibility

...But no clue about the other settings.

I plan to make the app available on the App Store in the future, but if the only way to do so is and hack with a private API, that's fine.

Any ideas?

Thanks in advance

Upvotes: 2

Views: 1149

Answers (2)

Kurt L.
Kurt L.

Reputation: 702

I have some success removing the close button on Catalyst by calling a function from the viewDidAppear(). I called it AppDelegate().disableTitleBarButtons(). Has to be from view did appear.

AppDelegate().disableTitleBarButtons() is as follows

func disableTitleBarButtons() {
        func bitSet(_ bits: [Int]) -> UInt {
            return bits.reduce(0) { $0 | (1 << $1) }
        }

        func property(_ property: String, object: NSObject, set: [Int], clear: [Int]) {
            if let value = object.value(forKey: property) as? UInt {
                object.setValue((value & ~bitSet(clear)) | bitSet(set), forKey: property)
            }
        }

        // disable full-screen button
        if  let NSApplication = NSClassFromString("NSApplication") as? NSObject.Type,
            let sharedApplication = NSApplication.value(forKeyPath: "sharedApplication") as? NSObject,
            let windows = sharedApplication.value(forKeyPath: "windows") as? [NSObject]
        {
            for window in windows {
                let resizable = 4
                property("styleMask", object: window, set: [], clear: [resizable])
                let fullScreenPrimary = 7
                let fullScreenAuxiliary = 8
                let fullScreenNone = 9
                property("collectionBehavior", object: window, set: [fullScreenNone], clear: [fullScreenPrimary, fullScreenAuxiliary])
            }
        }
    }

Where is says let resizable = 4, Change to 3 for no Maximise, Change to 2 for No minimise, Change to 1 of No Close button.

Play with the other numbers or stylemask settings also. Good luck

Upvotes: 1

Hejazi
Hejazi

Reputation: 17005

There is no official API for doing that, but you can easily access the NSWindow instance and modify it directly. You can do that manually or using some library like Dynamic (Full disclosure: I'm the author):

let window = Dynamic.NSApplication.sharedApplication.delegate.hostWindowForUIWindow(uiWindow)

window.isOpaque = false
window.hasShadow = false
window.backgroundColor = Dynamic.NSColor.clearColor
window.styleMask = 0 /*borderless*/
window.isMovableByWindowBackground = true
window.level = 25 /*statusBar*/

Upvotes: 4

Related Questions