swiftmacosswiftuimacos-catalina

How to apply "acceptsFirstMouse" for app build with SwiftUI?


Let's imagine that I have an app for macOS (Catalina).

This app is not hidden. But another app is activated (front of all/ top most)

I want to catch click on the button/any other view (I'm using swiftUI, so everithing is a view) in case of click on my app.

How can I do this?


UPD: how to apply "acceptsFirstMouse" for app build with SwiftUI?


Solution

  • Well, for now there is no such instrument in SwiftUI API, but... it is not standalone in a desert, and Apple did not say that it is a replacement for Cocoa, moreover they show us how to integrate them and use best of both...

    So, here is possible approach...

    import Foundation
    import SwiftUI
    
    @available(macOS 12.0, *)
    public extension View {
        ///
        /// must cover other views(no confuse, it is transparent)
        /// // Usage (somewhere in your SwiftUI view stack)
        /// ```
        ///       Text("Click me")
        ///         .padding(20)
        ///         .background(Color.yellow)
        ///         .onTapGesture { print("Label tapped") }
        ///         .acceptsFirstMouse() // must cover other views (no confuse, it is transparent)
        /// ```
        func acceptsFirstMouse() -> some View {
            self.overlay(AcceptingFirstMouse())
        }
    }
    
    fileprivate class MyViewView : NSView {
        override func acceptsFirstMouse(for event: NSEvent?) -> Bool {
            return true
        }
    }
    
    // Representable wrapper (bridge to SwiftUI)
    fileprivate struct AcceptingFirstMouse : NSViewRepresentable {
        func makeNSView(context: NSViewRepresentableContext<AcceptingFirstMouse>) -> MyViewView {
            return MyViewView()
        }
        
        func updateNSView(_ nsView: MyViewView, context: NSViewRepresentableContext<AcceptingFirstMouse>) {
            nsView.setNeedsDisplay(nsView.bounds)
        }
        
        typealias NSViewType = MyViewView
    }
    

    backup