SwiftUI macOS: tracking the mouse in a view?

I've got macOS SwiftUI app that displays an image, currently using Image. I need to display information about the pixel under the mouse pointer (its position, color, etc.) in some text fields at the bottom of the window.

I can't find an appropriate event handler to attach to Image. Traditionally I would have used mouseEntered, mouseExited, and mouseMoved. These are available for an NSHostingView, but that's for wrapping native views.

I found onHover(), which takes the place of mouseEntered and mouseExited, but it neither works (the perform method is never called for me), nor does it provide movement and position.
Answered by JetForMe in 671987022
Unfortunately that only works while the mouse button is held down. I found an amazing solution, though, but the forum won't let me include a link to it. It's the SwiftUI-Lab (dot com) website, article The Power of the Hosting+Representable Combo.”

It's unfortunate that Apple seems to have completely omitted mouse tracking in views.
this is untested, you could try something like this:

Code Block
Image(...).highPriorityGesture(
DragGesture(minimumDistance: 1, coordinateSpace: .global)
.onChanged {
let theCGPoint = $0.location
...
})

Accepted Answer
Unfortunately that only works while the mouse button is held down. I found an amazing solution, though, but the forum won't let me include a link to it. It's the SwiftUI-Lab (dot com) website, article The Power of the Hosting+Representable Combo.”

It's unfortunate that Apple seems to have completely omitted mouse tracking in views.
nice solution and article from SwiftUI-Lab. It seems you could achieve something similar with just the following:
(let me know if this works for you)

Code Block
struct ContentView: View {
var mouseLocation: NSPoint { NSEvent.mouseLocation }
@State var overImg = false
var body: some View {
Image(systemName: "clock").resizable().frame(width: 444, height: 444)
.onHover { over in
overImg = over
}
.onAppear(perform: {
NSEvent.addLocalMonitorForEvents(matching: [.mouseMoved]) {
if overImg {
print("mouse: \(self.mouseLocation.x) \(self.mouseLocation.y)")
}
return $0
}
})
}
}

For macOS 13.0 and iPadOS 16.0 or newer you can use onContinuousHover, although it does not seem to work with the mouse button held down.


    public func onContinuousHover(coordinateSpace: CoordinateSpace = .local, perform action: @escaping (HoverPhase) -> Void) -> some View

SwiftUI macOS: tracking the mouse in a view?
 
 
Q