macoscocoanstouchbar

Replacing the ESC button on a NSTouchBar


I am building a NSTouchBar for my app using storyboard.

I want to replace the ESC button with something else.

As usual, there is no doc telling you how to do that.

I have searched the web and I have found vague informations like

You can change the content of "esc" to something else, though, like "done" or anything, even an icon, by using escapeKeyReplacementItemIdentifier with the NSTouchBarItem.

But this is too vague to understand.

Any ideas?


This is what I did so far.

I have added a button to NSTouchBar on storyboard and changed its identifier to newESC. I added this line programmatically:

self.touchBar.escapeKeyReplacementItemIdentifier = @"newESC";

When I run the App the ESC key is now invisible but still occupies its space on the bar. The button that was supposed to replace it, appears next to it. So that bar that was

`ESC`, `NEW_ESC`, `BUTTON1`, `BUTTON2`, ...

is now

`ESC` (invisible), `NEW_ESC`, `BUTTON1`, `BUTTON2`, ...

The old ESC is still occupying its space on the bar.


Solution

  • This is done by creating a touch bar item, let's say a NSCustomTouchBarItem containing a NSButton, and associating this item with its own identifier.

    Then with another identifier you do your usual logic but you add the previously created identifier as the ESC replacement.

    Quick example in Swift:

    func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItemIdentifier) -> NSTouchBarItem? {
    
        switch identifier {
        case NSTouchBarItemIdentifier.identifierForESCItem:
            let item = NSCustomTouchBarItem(identifier: identifier)
            let button = NSButton(title: "Button!", target: self, action: #selector(escTapped))
            item.view = button
            return item
        case NSTouchBarItemIdentifier.yourUsualIdentifier:
            let item = NSCustomTouchBarItem(identifier: identifier)
            item.view = NSTextField(labelWithString: "Example")
            touchBar.escapeKeyReplacementItemIdentifier = .identifierForESCItem
            return item
        default:
            return nil
        }
    
    }
    
    func escTapped() {
        // do additional logic when user taps ESC (optional)
    }
    

    I also suggest making an extension (category) for the identifiers, it avoids making typos with string literals:

    @available(OSX 10.12.2, *)
    extension NSTouchBarItemIdentifier {
        static let identifierForESCItem = NSTouchBarItemIdentifier("com.yourdomain.yourapp.touchBar.identifierForESCItem")
        static let yourUsualIdentifier = NSTouchBarItemIdentifier("com.yourdomain.yourapp.touchBar.yourUsualIdentifier")
    }