Working on a Cocoa App where the app needs to do two things in case - :
1) mouse entered or exited
2) mouse dragged files to the app
I have view A, view A is registered for receiving dragging events and has tracking area for receiving mouse entered and exited events,
Issue is: If I drag files to the view A; view A receives the mouseEntered: event instead of draggingEntered: event.
- (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender
{
NSLog(@"draggingEntered called");
}
- (void)mouseEntered:(NSEvent *)theEvent
{
NSLog(@"mouseEntered called");
}
2018-02-05 14:08:58.273 XXX_APP [3420:119122] mouseEntered called
2018-02-05 14:08:58.273 XXX_APP [3420:119122] draggingEntered called
Issue is whenever I drag files to the view; It goes into the mouseEntered() not into the mouseDragged(). Is there any workaround for this?
Thanks in advance.
I may be wrong but I believe a drag operation is dependent on the mouse entering the view so if you're tracking mouse events, the mouseEntered:
method will always be called first. That said, you can delay doing something with the mouseEntered:
event giving the view time to see if it is followed by a drag operation and, if so, cancel the mouseEntered:
call. This can be done using performSelector:withObject:afterDelay:
(using a very brief delay that is probably not noticeable to the user) and cancelPreviousPerformRequestsWithTarget:
like so:
- (void)updateTrackingAreas {
[super updateTrackingAreas];
for (NSTrackingArea *trackingArea in self.trackingAreas) {
[self removeTrackingArea:trackingArea];
}
[self addTrackingArea:[[NSTrackingArea alloc] initWithRect:self.bounds options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil]];
}
- (void)_mouseEntered:(NSEvent *)event {
NSLog(@"mouseEntered");
//do something...
}
- (void)mouseEntered:(NSEvent *)event {
//pause 0.05 seconds before acting on this event,
//giving the view time to see if a draggingEntered: event is triggered
[self performSelector:@selector(_mouseEntered:) withObject:event afterDelay:0.05];
}
- (void)mouseExited:(NSEvent *)event {
NSLog(@"mouseExited");
//do something...
}
//assumes you've registered for drag events (e.g., in init):
// [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
//cancel pending _mouseEntered: call:
[NSObject cancelPreviousPerformRequestsWithTarget:self];
NSLog(@"draggingEntered");
NSPasteboard *pasteboard = [sender draggingPasteboard];
return (([pasteboard.types containsObject:NSFilenamesPboardType]) ? NSDragOperationLink : NSDragOperationNone);
}
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
NSPasteboard *pasteboard = [sender draggingPasteboard];
if ([pasteboard.types containsObject:NSFilenamesPboardType]) {
for (NSString *filePath in [pasteboard propertyListForType:NSFilenamesPboardType]) {
NSLog(@"dropped file: %@", filePath);
}
}
return YES;
}