Override right click in SwiftUI

Viewed 22

I try to add additional functionality when doing a right click. Unfortunately, this will break the .context modifier and I don't understand why. This is the code I am using:

extension View {
    func onRightClick(handler: @escaping () -> Void) -> some View {
        modifier(RightClickHandler(handler: handler))
    }
}

struct RightClickHandler: ViewModifier {
    let handler: () -> Void
    func body(content: Content) -> some View {
        content.overlay(RightClickListeningViewRepresentable(handler: handler), alignment: .center)
    }
}

struct RightClickListeningViewRepresentable: NSViewRepresentable {
    let handler: () -> Void
    func makeNSView(context: Context) -> RightClickListeningView {
        RightClickListeningView(handler: handler)
    }
    func updateNSView(_ nsView: RightClickListeningView, context: Context) {}
}

class RightClickListeningView: NSView {
    let handler: () -> Void
    
    init(handler: @escaping () -> Void) {
        self.handler = handler
        super.init(frame: .zero)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func rightMouseDown(with event: NSEvent) {
        handler()
        super.rightMouseDown(with: event)
        if let menu = super.menu(for: event) {
            print(menu)
            let location = event.locationInWindow
            menu.popUp(positioning: nil, at: location, in: self)
        }
    }

}

Later then, I have this:

struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .contextMenu(menuItems: {
                Button("Test") { }
            })
            .onRightClick {
                print("right click detcted")
            }
            .padding()
    }
}

If I remove the onRightClick-modifier, the context menu works again.

0 Answers
Related