Мы сделаем программу для запуска приложений из панели статуса.
Вам понадобится terminal, Swift версии 3.1 или выше и любой текстовый редактор.
Я проверял работу на macOS Sierra 10.12.6 и macOS Catalina 10.15.
Открываем terminal /Applications/Utilities/Terminal и создаем файл.
touch toolbar.swift
Открываем файл toolbar.swift и пишем такой код:
import AppKit
var app: NSApplication
var statusItem: NSStatusItem
#if swift(>=5.1)
app = NSApplication.shared
statusItem = NSStatusBar.system.statusItem(
withLength: CGFloat(NSStatusItem.variableLength))
#else
app = NSApplication.shared()
statusItem = NSStatusBar.system().statusItem(withLength: CGFloat(32))
#endif
if #available(macOS 10.10, *) {
statusItem.button?.title = "\u{2699}\u{FE0F}"
}
// extension
// menu
app.setActivationPolicy(.prohibited)
app.run()
Часть кода нужна, чтобы поддерживать совместимость со старыми версиями языка.
Строка app.setActivationPolicy(.prohibited) нужна, чтобы иконка активного приложения не появилась в Dock.
Сохраните файл и запустите программу командой:
swift toolbar.swift
Если нет ошибок, то на панели статуса появится «бесполезная» кнопка. Я использовал UTF символ шестеренки "\u{2699}\u{FE0F}", но можно добавить нужную вам картинку используя свойство statusItem.button?.image.
Выйдите из программы нажав в terminal ctrl-c.
Я решил не создавать class AppDelegate для такого маленького приложения, а расширил класс NSApplication. Добавьте после // extension следующие строки:
extension NSApplication {
func runTask(_ appName: String, _ arg: String = "") {
let task = Process()
#if swift(>=5.1)
task.executableURL = URL(fileURLWithPath: "/usr/bin/open")
#else
task.launchPath = "/usr/bin/open"
#endif
task.arguments = arg.isEmpty ?[appName] : [arg, appName]
#if swift(>=5.1)
do {try task.run()}
catch {print(error)}
#else
task.launch()
#endif
}
@objc func securityRun () {
self.runTask("/System/Library/PreferencePanes/Security.prefPane")
}
@objc func diskRun () {
self.runTask( "disk utility", "-a")
}
@objc func automatorRun () {
self.runTask( "automator", "-a")
}
}
Обратите внимание, что таким образом можно быстрее запускать не только приложения, но и отдельные страницы SystemPreference.
Для методов нужен интерфейс. После // menu наберите:
let menu = NSMenu()
let items: [String] = ["Security", "Disk Utility", "Automator", "Quit"]
var sel: [Selector] = []
let shared = NSApplication.shared
#if swift(>=5.1)
sel = [
#selector(shared.securityRun), #selector(shared.diskRun),
#selector(shared.automatorRun), #selector(shared.terminate)]
#else
sel = [
#selector(shared().securityRun), #selector(shared().diskRun),
#selector(shared().automatorRun), #selector(shared().terminate)]
#endif
for i in 0..<items.count {
menu.addItem(NSMenuItem(
title: items[i], action: sel[i], keyEquivalent: ""))
if i==items.count-2 {
menu.addItem(NSMenuItem.separator())
}
}
statusItem.menu = menu
Для всех методов мы создали кнопки и привязали к ним методы из экземпляра класса NSApplication. Мы добавили кнопку «Quit», так как нам надо позволить пользователю выйти из программы без использования terminal.
Компилируем программу. Обратите внимание, что вместо swift надо набрать swiftc.
swiftc toolbar.swift
В текущей директории появился файл toolbar. Его можно запустить командой:
./toolbar
Если мы запустим файл toolbar двойным кликом, то вместе с приложением появится окно terminal, а это не очень удобно.
Попробуем исправить ситуацию. Все команды запускаем в terminal.
Для начала создаем дерево директорий для нашего приложения.
mkdir -p ToolBar.app/Contents/MacOS
Меняем доступ к приложению.
chmod a+x ToolBar.app
Создаем директорию для иконки.
mkdir ToolBar.app/Contents/Resources
Копируем и изменяем имя одной из стандартных иконок.
cp /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/ToolbarAdvanced.icns ToolBar.app/Contents/Resources/AppIcon.icns
Перемещаем скомпилированный файл toolbar в директорию MacOS.
mv toolbar ToolBar.app/Contents/MacOS
Меняем режим доступа к файлу toolbar.
chmod a+x ToolBar.app/Contents/MacOS/toolbar
Cоздаем файл PkgInfo с информацией о типе приложения. Флаг -n нужен, чтобы в файле PkgInfo не было символа перевода строки.
echo -n "APPL????" > ToolBar.app/Contents/PkgInfo
Меняем режим доступа к файлу PkgInfo.
chmod a+x ToolBar.app/Contents/PkgInfo
Создаем минимальный Info.plist с информацией о приложении:
echo '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>example.ToolBar</string>
<key>CFBundleExecutable</key>
<string>toolbar</string>
<key>CFBundleIconFile</key>
<string>AppIcon</string>
</dict>
</plist>' > ToolBar.app/Contents/Info.plist
Перемещаем приложение ToolBar.app в /Applications/Utilities.
Terminal попросит ввести пароль администратора.
sudo mv ToolBar.app /Applications/Utilities
После этих операций новое приложение должно появится в /Applications/Utilities и его можно запустить через Launchpad (почему-то директория с утилитами называется Others)
Осталось добавить наше приложение в автозапуск.
Для этого надо создать файл ~/Library/LaunchAgents/example.ToolBar.plist. Сделаем это одно командной:
echo '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>example.ToolBar</string>
<key>ProgramArguments</key>
<array>
<string>open</string>
<string>/Applications/Utilities/ToolBar.app</string>
<string>--args</string>
<string>-silent</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>' > ~/Library/LaunchAgents/example.ToolBar.plist
Проверьте появился ли нужный файл.
ls ~/Library/LaunchAgents
Чтобы проверить автозапуск без перезагрузки, выйдите из приложения и запустите в terminal команду:
launchctl load -w ~/Library/LaunchAgents/example.ToolBar.plist
Иконка приложения должна появится на панели статуса.
Выйдите из приложения и сделайте unload командой:
launchctl unload -w ~/Library/LaunchAgents/example.ToolBar.plist
Теперь приложение запустится при перезагрузке системы, а лишние иконки можно убрать из Dock.
Скорее всего, таким способом можно сделать мини-плеер для iTunes, простой todo list или интерфейс для выравнивания окон на рабочем столе.
dvmedvedev
Я тоже когда-то пытался писать приложения для панели статуса, а потом открыл для себя bitbar.
veledzimovich Автор
Отличная штука. Спасибо.
veledzimovich Автор
Т.е. с помощью это bitbar можно перенаправить выход любого приложения?