Search code examples
objective-ccocoansviewnsresponder

mouseDragged events get stolen by another view


I have several views of class MyView (subclass of NSView) inside another NSView. MyView implements -mouseEntered:, -mouseExited:, -mouseDown:, -mouseDragged:, and -mouseUp:.

Almost always, when a MyView receives a mouse-down event, all subsequent mouse-dragged events are received by the same MyView until the next mouse-up event. Even if the cursor goes outside of the MyView. That is the expected behavior.

Occasionally, a MyView will receive a mouse-down event, but will only receive mouse-dragged and mouse-up events while the cursor remains inside the MyView. If the cursor moves onto a different MyView, then that MyView starts receiving mouse-dragged events (without first receiving a mouse-down event) and can receive the subsequent mouse-up event.

In case it matters, the mouse-down event creates a FooView (subclass of NSView) on top of the MyView, and the mouse-dragged events resize the frame of the FooView. This might be related, as I've only been able to reproduce the problem after one of these FooViews has been created. FooView does not implement any of the mouse event methods.

I've been messing with this for a while now and haven't been able to either purposely reproduce the problem or recreate the problem in a simple example. I'd be happy to answer any questions about my code, I'm just not sure what would be the relevant part to post.


Solution

  • Not sure what the root issue is (this Cocoa behavior seems inconsistent to me)... but here's one possible workaround:

    1. In the superview, create an instance variable tracking the MyView instance in which the -mouseDown: occurred.
    2. When you receive a -mouseDragged: in MyView, instead of operating on self, operate on the MyView instance reference stored in the superview.

    ...then you'll be able to consistently track which object is being dragged, without having to run your own event loop.