6

I am trying to create a macOS menubar app which will have a text field as the first item. The textfield will serve as a search bar for filtering other items which will be displayed below it.

It should look very similar to 1password:

1password

This is what I managed to do:

mine

I have accomplished this by creating a Status menu with three items and creating a custom view for the first item in the menu.

However, this approach does not seem to solve my issue. When pressing cmd + A in the search field, the focus jumps to the next item in the menu. This is the default behaviour for NSMenu.

So, my question is: Is this the right approach to create a 1Password-like app or is there a better one?

Jerguš Lejko
  • 610
  • 4
  • 25

1 Answers1

3

Basically the approach is correct.

But you have to catch the edit key events explicitly. Subclass NSTextField and override performKeyEquivalent

class AXCVTextField: NSTextField {

    override func performKeyEquivalent(with event: NSEvent) -> Bool {
        if event.modifierFlags.contains(.command),
          let key = event.charactersIgnoringModifiers {
            var action : String?
            switch key {
            case "x": action = "cut:"
            case "c": action = "copy:"
            case "v": action = "paste:"
            case "a": action = "selectAll:"
            default:
                break
            }
            if let action = action {
                return NSApp.sendAction(Selector(action), to:self.window!.firstResponder, from:self)
            }
        }
        return super.performKeyEquivalent(with: event)
    }
}
vadian
  • 274,689
  • 30
  • 353
  • 361
  • I have created a subclass `class SearchField: NSTextField {...}` and set it as `NSTextField`'s class. However, the method is not triggered when I press `cmd + A`. Also, I just realised that sometimes when I run the app, I cannot click on the input. It becomes unresponsive but other `NSMenuItem`s work properly. – Jerguš Lejko Oct 23 '17 at 17:46
  • Of course you have to design your views that the text field is in the responder chain to receive the key events. – vadian Oct 23 '17 at 19:06
  • Care to explain in a bit more detail? I'm having trouble googling it – Jerguš Lejko Oct 23 '17 at 21:02
  • To be able to receive (key) events the view must be in a window which can become the key window. I guess 1Password uses a separate window controller rather than a simple `NSMenu` – vadian Oct 23 '17 at 21:06
  • would you suggest that I replace `NSMenu` with a custom window that shows up in place where `NSMenu` does by default and implement everything in that window? – Jerguš Lejko Oct 23 '17 at 21:24
  • There are probably a few solutions, as mentioned in any case you need a **key window** – vadian Oct 23 '17 at 21:28
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/157321/discussion-between-jergus-lejko-and-vadian). – Jerguš Lejko Oct 23 '17 at 22:49