5
votes

I have an NSWindow with a main "OK" button. This button has as "key equivalent" property in interface builder, the key ENTER i.e .

It works good, but now I have a new NSComboBox, which is supposed to invoke a method when the user selects a list item, or he preses Enter / .

However, when I press Enter, the main Button receive the notification and the window close. How to prevent this?

3
Hey I think you have had bounty for this one, isn't it?Anoop Vaidya

3 Answers

4
votes

This is the normal behavior what you are getting, but you can hack a bit, by removing and adding the key-equivalent.

Add following delegates of NSComboBox:

- (void)comboBoxWillPopUp:(NSNotification *)notification;{
    [self.closeButton setKeyEquivalent:@""];
}


- (void)comboBoxWillDismiss:(NSNotification *)notification;{
    [self.closeButton setKeyEquivalent:@"\r"];
}
0
votes

One way you can workaround for prevent enter notification is like that below:-

//Connect this action method to your combobbox and inside that set one BOOL flag to yes

- (IBAction)comBoxItm:(id)sender
{
    self.isEnterCalled=YES;
}

//Now check this flag to your some method where close window is called

-(void)someMethod
{
//Check the flag value if it is yes then just ignore it
if (!self.isEnterCalled)
{
//Close window logic
}
self.isEnterCalled=NO;
}
0
votes

Ran into the same problem. Had "hot key" which I'd like to switch off while editing some text fields. I found solution for myself. There's no need in override lots of NSTextField base methods.

Firstly, I removed all the "key equivalents". I used to detect Enter key down with the + (void)addLocalMonitorForEventsMatchingMask:(NSEventMask)mask handler:(NSEvent *(^)(NSEvent *))block class method of NSEvent. You pass block as a parameter, where you can check for some conditions. The first parameter is the event mask. For your task it would be NSKeyDownMask, look for other masks at the NSEvent Reference Page

The parameter block will perform each time the user pushes the button. You should check if it is right button pushed, and - generally - if the current window first responder isn't some editable control. For that purposes we need NSWindow category class just not to implement this code each time we deal with NSKeyDownMasked local monitors.

NSWindow+Responders class listing:

@interface NSWindow (Responders)

- (BOOL)isEditableFirstResponder;

@end

@implementation NSWindow (Responders)

- (BOOL)isEditableFirstResponder
{
  if (!self.firstResponder)
    return NO; // no first responder at all
  if ([self.firstResponder isKindOfClass:[NSTextField class]]) // NSComboBox is NSTextField subclass
    {
      NSTextField *field=(NSTextField *)self.firstResponder;
      return field.isEditable;
    }
  if ([self.firstResponder isKindOfClass:[NSButton class]]) // yep, buttons may be responders
    return YES;
  return NO; // the first responder is not NSTextField or NSButton subclass - not editable
}

@end

Don't know if there's another way to check if we are now editing some text field or combo box. So, there's at least the part you add the local monitor somewhere in your class (NSWindow, NSView, some controller etc.).

- (void)someMethod
{
  id monitor=[NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask handler:(NSEvent *)^(NSEvent *theEvent){
    if (theEvent.keyCode==/*Enter key code*/ && ![self.window.isEditableFirstResponder]) // you should check the key modifiers too
    {
      // your code here
    }
    return theEvent; // you may return the event to pass the key to the receiver
  }];
} 

Local monitors is safe remedy about the Apple rules. It works only inside your application. For global key down events you may use addGlobalMonitor but Apple may reject your app from the AppStore.

And don't forget to remove the monitor when there's no need in it.

- (void)viewControllerShutdownMethod
{
  [NSEvent removeMonitor:monitor];
}

Good luck.