Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C++ interop flag makes NSTrackingArea behave differently #65885

Closed
ByunghoonKim opened this issue May 12, 2023 · 4 comments
Closed

C++ interop flag makes NSTrackingArea behave differently #65885

ByunghoonKim opened this issue May 12, 2023 · 4 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. c++ interop Feature: Interoperability with C++ triage needed This issue needs more specific labels

Comments

@ByunghoonKim
Copy link

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
@ByunghoonKim ByunghoonKim added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels labels May 12, 2023
@hyp hyp self-assigned this May 12, 2023
@hyp hyp added the c++ interop Feature: Interoperability with C++ label May 12, 2023
@linshaolong5240
Copy link

When -enable-experimental-cxx-interop flag is added to Project > Build Settings > Swift Compiler - Custom Flags > Other Swift Flags

/// Type 'NSSearchPathDomainMask' (aka 'Int') has no member 'userDomainMask'
try? FileManager.default.url(for: .downloadsDirectory, in: .userDomainMask, appropriateFor: nil, create: false)

///Reference to member 'atomic' cannot be resolved without a contextual type
///Value of type 'Data' has no member 'write'
let data = Data()
data.write(to: url, options: [.atomic])

/// Value of type 'CGBitmapInfo' (aka 'UInt32') has no member 'rawValue'
  public func resize(in rect: CGRect, size: CGSize) -> CGImage? {
      guard let context = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: self.bitsPerComponent, bytesPerRow: self.bitsPerComponent * Int(size.width), space: self.colorSpace!, bitmapInfo: self.bitmapInfo.rawValue) else {
          return nil
      }
      context.draw(self, in: rect)
      guard let cgImage = context.makeImage() else {
          return nil
      }
      return cgImage
  }

@zoecarver
Copy link
Collaborator

@ByunghoonKim I think your issue is resolved on main.

@linshaolong5240 this PR will resolve your issue: #66452

@ByunghoonKim
Copy link
Author

ByunghoonKim commented Jun 9, 2023

Thank you for the update.
@zoecarver And I have to say, I enjoyed your WWDC23 "Mix Swift and C++" presentation. :)

@zoecarver
Copy link
Collaborator

Thank you, Byunghoon!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. c++ interop Feature: Interoperability with C++ triage needed This issue needs more specific labels
Projects
None yet
Development

No branches or pull requests

4 participants