I'm trying to add support for exposing NSTouchBar
buttons via a plugin to an application that I cannot otherwise modify. The plugin, a shared library, is loaded at runtime after the main window has been created. I've created an AppDelegate
as follows:
@interface AppDelegate : NSResponder <NSTouchBarDelegate>
@end
With an @implmentation
that implements the makeTouchBar
and touchBar
functions:
- (NSTouchBar *) makeTouchBar
- (nullable NSTouchBarItem *) touchBar:(NSTouchBar *)touchBar
makeItemForIdentifier: (NSTouchBarItemIdentifier)identifier
I finally try to inject it into the application, I have the following in the onload
function that's called in the dynamic library when it's loaded into the application.
NSWindow *w = [NSApp mainWindow];
AppDelegate *a = [[AppDelegate alloc] init];
a.nextResponder = w.nextResponder;
w.nextResponder = a;
// Re-setting FirstResponder will trigger AppDelegate::makeTouchBar
// that was attached above.
NSResponder *n = w.firstResponder;
[w makeFirstResponder: nil];
[w makeFirstResponder: n];
however... AppDelegate::touchBar
will never be called, thus the touchbar will never be populated with my test buttons.
If I create a new project in Xcode, and use the exact same AppDelegate
implementation (copy-paste of the same @interface
and @implementation
), I get functional buttons that are both shown and responds to press events, so it's the injection part that seems to be broken. (In Xcode everything is hooked up via MainMenu.xib
I guess)
Update: The main problem was that the application was compiled in a way that prevented TouchBar to work. Perhaps built on an older version of Mac OS.
If this object really should act as the application delegate (as the name suggests) -- rather than inserting it in the main window's responder chain, it would be better to actually set it as the NSApp's delegate
. The set delegate's touchBar is also used when building the touch bar (see NSTouchBar Discovery and the Responder Chain).
If that doesn't work for your plugin (maybe the application already has a specific app delegate it needs), you could insert it into NSApp's responder chain instead of the mainWindow
's.
Both of these also have the benefit of making the touch bar be associated at the application level rather than window. So if the main/key window changes, the provided touch bar will always be used.