This widget shows native input source icon.
Story about trying to get the icon without external binary
NSBezierPath working, but nothing I couldn't figure out. The biggest issue probably was that Mojave just crashes when you try to work with NSRect structure from JXA. You can't use it at all: creating, getting it as a result of another method, even
NSZeroRect. Nothing works - straight crash.
Anyway, I managed to make the widget work and looked at my touch bar. One last missing piece was an input source switcher. There are a couple available on this forum, but all of them suffer from the very same problem - they don't show original macOS input source icon. Usually they just show emoji flag.
It looks like macOS doesn't expose input source icons as files, so you have to use Carbon API to get it:
TISInputSourceRef currentSource = TISCopyCurrentKeyboardInputSource(); IconRef iconRef = (IconRef)TISGetInputSourceProperty(currentSource, kTISPropertyIconRef); NSImage *image = [[NSImage alloc] initWithIconRef:iconRef];
Fair enough, this could be easily translated to JXA:
var currentSource = $.TISCopyCurrentKeyboardInputSource(); var iconRef = $.TISGetInputSourceProperty(currentSource, $.kTISPropertyIconRef); var image = $.NSImage.alloc.initWithIconRef(iconRef);
Except this code doesn't work, it produces an error (not a crash luckily) "Ref has incompatible type". Apparently
initWithIconRef expects some other type of IconRef .
So current solution is to use an external binary:
var app = Application.currentApplication(); app.includeStandardAdditions = true; var localeBase64Script = "/usr/local/bin/localebase64icon" var icon = app.doShellScript(localeBase64Script)
I believe that this widget should be a part of default widget set. The native code is relatively straightforward, the problem with lag would go away - currently icon refreshes every so often, so when you change input source, it may take some time to reflect the change on touch bar.
Anyway, here's the link to the widget, hope it would be useful for someone . And don't forget to install the localebase64icon binary before using the widget.
After installing the widget, open the widget's settings and make sure that the combobox says "Java Script for Automation", not "AppleScript"
In order to switch language by tapping on the widget, you need to assign a custom hotkey in the keyboard settings, and add a custom keyboard shortcut to the widget's settings: