Skip to content

C++ interop flag makes NSTrackingArea behave differently #65885

Closed
@ByunghoonKim

Description

@ByunghoonKim

Description
When -enable-experimental-cxx-interop flag is added to Project > Build Settings > Swift Compiler - Custom Flags > Other Swift Flags, Xcode suddenly complains

'Option' is not a member type of class 'AppKit.NSTrackingArea'.

Without the flag, this works:

let opt: NSTrackingArea.Options = [.mouseEnteredAndExited, .mouseMoved, .activeInKeyWindow, .inVisibleRect]

With the flag, this works:

let opt: NSTrackingAreaOptions = NSTrackingMouseEnteredAndExited|NSTrackingMouseMoved|NSTrackingActiveInKeyWindow|NSTrackingInVisibleRect

Steps to reproduce

struct ContentView: View {
    var body: some View {
        VStack {
            Text("hi")
                .frame(width:400, height:400)
                .border(.red)
                .mouseTracking()

        }
        .padding()
    }
}
import SwiftUI
import AppKit

extension View {
    func mouseTracking() -> some View {
        self.modifier(MouseTrackingViewModifier())
    }
}

struct MouseTrackingViewModifier: ViewModifier {
    func body(content: Content) -> some View {
        content.background {
            GeometryReader { geom in
                MouseTrackingViewRep(frame: geom.frame(in: .local))
            }
        }
    }
}

struct MouseTrackingViewRep: NSViewRepresentable {
    let frame: NSRect
    
    typealias NSViewType = MouseTrackingView
    
    func makeNSView(context: Context) -> NSViewType {
        MouseTrackingView(self, frame: frame)
    }
    
    func updateNSView(_ nsView: NSViewType, context: Context) {
    }
}

class MouseTrackingView: NSView {    
    let parent: MouseTrackingViewRep
    override var isFlipped: Bool { true }
    
    init(_ parent: MouseTrackingViewRep, frame: NSRect) {
        self.parent = parent
        super.init(frame: frame)
                
        // when Swift only
        let opt: NSTrackingArea.Options = [.mouseEnteredAndExited, .mouseMoved, .activeInKeyWindow, .inVisibleRect]
        // when -enable-experimental-cxx-interop
//        let opt: NSTrackingAreaOptions = NSTrackingMouseEnteredAndExited|NSTrackingMouseMoved|NSTrackingActiveInKeyWindow|NSTrackingInVisibleRect
        let trackingArea = NSTrackingArea(rect: self.bounds, options: opt, owner: self, userInfo: nil)
        self.addTrackingArea(trackingArea)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func mouseEntered(with event: NSEvent) {
        print("mouse Entered")
    }
    
    override func mouseExited(with event: NSEvent) {
        print("mouse Exited")
    }
    
    override func mouseMoved(with event: NSEvent) {
        let mouseLocation = self.convert(event.locationInWindow, from: nil)
        print("mouse (\(mouseLocation.x), \(mouseLocation.y))")
    }
}

Expected behavior

Either changing the code is not required, or some documentation of the behavior.

Environment

  • Swift compiler version info
swift-driver version: 1.75.2 Apple Swift version 5.8 (swiftlang-5.8.0.124.2 clang-1403.0.22.11.100)
Target: arm64-apple-macosx13.0
  • Xcode version info
Xcode 14.3
Build version 14E222b
  • Deployment target:
    macOS 13.3

Metadata

Metadata

Assignees

Labels

bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.c++ interopFeature: Interoperability with C++triage neededThis issue needs more specific labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions