Re: a mouse event problem on macOS
Graham Cox
The mouseDragged goes to the view that handled the mouseDown. Since that’s not the same view, you don’t get the mouseDragged.
toggle quoted messageShow quoted text
But it’s pretty easy to fix this. On the mouseDown, create and show your overlay view. Then call its mouseDown from your mouseDown. Within the overlay’s mouseDown, implement your own mouse tracking loop which keeps control until the mouse goes up. This approach is sufficiently general that I have a handy category on NSView to deal with it. It’s also a documented and officially supported way to do this. typedef void(^GCEventTrackingBlock)( NSEvent* event, BOOL* shouldEndTracking ); @interface NSView (EventTrackingBlock) - (void) trackMouseEvent:(NSEvent*) initialMouseDownEvent usingBlock:(GCEventTrackingBlock) eventBlock; - (void) trackEvents:(NSEventMask) eventTypes usingBlock:(GCEventTrackingBlock) eventBlock; - (void) trackEvents:(NSEventMask) eventTypes untilDate:(NSDate*) date dequeue:(BOOL) dequeue usingBlock:(GCEventTrackingBlock) eventBlock; @end @implementation NSView (EventTrackingBlock) - (void) trackMouseEvent:(NSEvent*) initialMouseDownEvent usingBlock:(GCEventTrackingBlock) eventBlock { // designed to be called from a -mouseDown: method, the initial event is passed to the block, and then unless the block cancelled it, it will // enter a tracking loop for all other LEFT mouse events. BOOL shouldEndTracking = NO; eventBlock( initialMouseDownEvent, &shouldEndTracking ); if( !shouldEndTracking ) { // tracks left mouse events plus flagsChanged. Tracks mouseMoved events if the view is set to report them. [self trackEvents:NSLeftMouseDownMask | NSLeftMouseDraggedMask | NSLeftMouseUpMask | NSMouseMovedMask | NSFlagsChangedMask usingBlock:eventBlock]; } } - (void) trackEvents:(NSEventMask) eventTypes usingBlock:(GCEventTrackingBlock) eventBlock { [self trackEvents:eventTypes untilDate:[NSDate distantFuture] dequeue:YES usingBlock:eventBlock]; } - (void) trackEvents:(NSEventMask) eventTypes untilDate:(NSDate*) date dequeue:(BOOL) dequeue usingBlock:(GCEventTrackingBlock) eventBlock { BOOL shouldEndTracking = NO; while( !shouldEndTracking ) { NSEvent* event = [self.window nextEventMatchingMask:eventTypes untilDate:date inMode:NSEventTrackingRunLoopMode dequeue:dequeue]; [self.window discardEventsMatchingMask:NSAnyEventMask beforeEvent:event]; // if a timeout occurred and event is nil, the loop will end after invoking the block unless the block resets the flag to NO. if( event == nil ) shouldEndTracking = YES; eventBlock( event, &shouldEndTracking ); } } @end The event tracking block needs to look at event.type to see whether it’s a drag, mouse up, flags changed, etc. Usually you do that in a switch statement. —Graham
On 20 Sep 2017, at 10:54 am, James Walker <list2@...> wrote:
|
|