Force NSPopover will not be the first responder with NSTokenField

I have an NSTokenField and I provide custom autocomplete inside a popover. Unfortunately, as soon as a popup appears, it forces the NSTokenField to resign. Is there a way to show a popover but not lose the first responder on an NSTokenField?

Overriding the NSTokenField resignFirstResponder causes the NSTokenField to stop working (it does not accept any keystrokes). Overriding NSPopover accepts the FirstResponder method or sets its behavior, as suggested in this , the question does not work either.

Edit: NSTokenField is not inside the contents of contentViewController.view. Edit2: Such behavior as the search bar in Mailapp would be the best solution. Mailapp

Popover

+4
cocoa macos nspopover
source share
2 answers

Unfortunately, there is no clean way to do this. Fortunately, however, I did it in an ugly way in Delicious Library 3 — you need to put this method in a subclass of NSWindow and make sure the document in question is a subclass:

- (BOOL)makeFirstResponder:(NSResponder *)responder; { // Prevent popover content view from forcing our current first responder to resign if (responder != self.firstResponder && [responder isKindOfClass:[NSView class]]) { NSWindow *const newFirstResponderWindow = ((NSView *)responder).window; NSWindow *currentFirstResponderWindow; NSResponder *const currentFirstResponder = self.firstResponder; if ([currentFirstResponder isKindOfClass:[NSWindow class]]) currentFirstResponderWindow = (id)currentFirstResponder; else if ([currentFirstResponder isKindOfClass:[NSView class]]) currentFirstResponderWindow = ((NSView *)currentFirstResponder).window; // Prevent some view in popover from stealing our first responder, but allow the user to explicitly activate it with a click on the popover. // Note that the current first responder may be in a child window, if it a control in the "thick titlebar" area and we're currently full-screen. if (newFirstResponderWindow != self && newFirstResponderWindow != currentFirstResponderWindow && self.currentEvent.window != newFirstResponderWindow) for (NSView *responderView = (id)responder; responderView; responderView = responderView.superview) if ([responderView conformsToProtocol:@protocol(LIPopoverFirstResponderStealingSuppression)] && ((id <LIPopoverFirstResponderStealingSuppression>)responderView).suppressFirstResponderWhenPopoverShows) return NO; } return [super makeFirstResponder:responder]; } 

Now make sure that subclasses of popovers content view implement this protocol:

 // NSPopover doesn't respect -acceptsFirstResponder of its content view (Radar 10666891). @protocol LIPopoverFirstResponderStealingSuppression <NSObject> @property (readonly, nonatomic) BOOL suppressFirstResponderWhenPopoverShows; @end 

Please also report an error with Apple to request respect for NSPopover -acceptsFirstResponder its contents; this is a 100% case where several developer file errors are fixed.

+7
source share

Subclass your content popover (text view?) And implement -(void)canBecomeKeyView . Return NO. It is called only once when a popover is displayed, so you can interact with it, but it no longer steals the status of the first responder.

0
source share

All Articles