0

In an NSTextView I am trying to make tab and shift-tab play a role in editing text, without tabs being inserted in the text. Currently I am detecting keypresses via NSTextViewDelegate's keyUp method:

override func keyUp(with event: NSEvent) { if let currChar = event.characters { if event.keyCode == 48 { // detect tab key if event.modifierFlags.rawValue == 256 { // detect no modifier key // do something } else if event.modifierFlags.rawValue == 131330 { // detect shift modifier // do another thing } } } 

I can't see anything in the documentation how to indicate to the NSTextView that I want it to ignore the tab key (I have tried the answer shown here, but tabs do not appear to trigger this event), or to prevent the event from moving up the responder chain.

I have also tried calling interpretKeyEvents([event]) at the beginning of my keyUp method, and overriding insertTab and insertBacktab. These are successfully called with the right keypresses, but a tab is still inserted into the text. The documentation seems to suggest it should prevent the tab being inserted:

It [keyDown] can pass the event to Cocoa’s text input management system by invoking the NSResponder method interpretKeyEvents:. The input management system checks the pressed key against entries in all relevant key-binding dictionaries and, if there is a match, sends a doCommandBySelector: message back to the view. Otherwise, it sends an insertText: message back to the view, and the view implements this method to extract and display the text. (emphasis mine)

The documentation talks about an event continuing up the responder chain if it has not been handled - how is this indicated? Is it important that I am using keyUp, not keyDown?

1
  • I just tried to subclass NSTextView with custom insertTab and no tab is being inserted. Is the delegate the right place to handle this? I feel you misunderstand responder chain for key events (what is the order of responding to keypress and when beep occurs). Check WWDC "Key Event Handling in Cocoa Applications from WWDC 2010" Commented Feb 23, 2018 at 7:21

2 Answers 2

1

Yes, it matters that you’re overriding keyUp: instead of keyDown:. The key-down event happens before the key-up event, and NSTextView acts on the key-down event. By the time the system has called your keyUp: override, it’s too late to prevent the default handling of the key-down event.

Sign up to request clarification or add additional context in comments.

1 Comment

thanks Rob. looks like I have more problem solving around getting keyDown to work, but at least I know I'm going in the right direction
1

Use custom subclass. If these methods are not being called it means the first responder is someone else and has eaten your event. As long as your textview is first responder your keyDown method will be called.

class MyTextView: NSTextView { override func insertTab(_ sender: Any?) { self.insertText("HELLO", replacementRange: NSMakeRange(0, 0)) //OR ANY CUSTOM TEXT EDITING, ACTION TO CHANGE FIRST RESPONDER... } override func insertBacktab(_ sender: Any?) { self.insertText("AAAAA", replacementRange: NSMakeRange(0, 0)) //OR ANY CUSTOM TEXT EDITING, ACTION TO CHANGE FIRST RESPONDER... } } 

Educational: "Key Event Handling in Cocoa Applications from WWDC 2010"

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.