AppKit takes care of forwarding mouse events to the window / view where these events occurred. If you want to catch mouse events elsewhere, you can use the local event monitor.
In a class that should implement this behavior, which probably belongs to the class to which the panel belongs, defines an instance variable or a declared property to store an instance of an event monitor:
@property (nonatomic, strong) id mouseEventMonitor;
When you show your panel, add a mouse event monitor:
self.mouseEventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:(NSLeftMouseDownMask | NSRightMouseDownMask | NSOtherMouseDownMask) handler:^NSEvent *(NSEvent *event) { if (event.window != self.panelWindow) [self dismissPanel]; return event; }];
When removing the panel, remove the mouse event monitor:
- (void)dismissPanel { if (self.mouseEventMonitor != nil) { [NSEvent removeMonitor:self.mouseEventMonitor]; self.mouseEventMonitor = nil; }
If you need to test a specific view instead of the entire window containing the panel, use -[NSView hitTest:] to check whether the mouse location ( event.locationInWindow ) event.locationInWindow to this view or to one of its subzones.
Edit:. To cancel the panel if the user clicks outside the application windows, observe the NSApplicationDidResignActiveNotification , which is published whenever the application resigns from its active state, which means that some other application has become active. When you show the panel:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dismissPanel) name:NSApplicationDidResignActiveNotification object:nil];
And when you remove the panel:
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidResignActiveNotification object:nil];
Edit:. To handle the case if the user clicked the menu bar (which does not send NSApplicationDidResignActiveNotification , because the application is still active), you should also observe the NSMenuDidBeginTrackingNotification sent to the main menu, [NSApp mainMenu] . When you show the panel:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dismissPanel) name:NSMenuDidBeginTrackingNotification object:[NSApp mainMenu]];
And when you remove the panel:
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSMenuDidBeginTrackingNotification object:[NSApp mainMenu]];