Pock 深度指南:在 MacBook Touch Bar 上打造你的 Widgets 管理面板

原创2026-10-13 19:04:401,924 阅读
文章标签:桌面应用插件系统

Pock 深度指南:在 MacBook Touch Bar 上打造你的 Widgets 管理面板

Pock 是一款面向 MacBook Touch Bar 的免费开源「Widgets 管理器」:它把 macOS Dock、正在播放的媒体信息、ESC 键、系统状态与控制中心等常用功能搬进 Touch Bar,帮助你在全屏工作或观影时最大化屏幕可用面积。本文以官方 README.md 为骨架,结合仓库源码逐层拆解 Pock 的安装、使用、内置 Widgets、偏好设置、自定义布局、Widgets 安装与更新机制,并深入到 AppController、WidgetsLoader、WidgetsInstaller、Updater 等核心实现,让普通用户能快速上手、开发者能理解其架构与扩展方式。

一、Pock 是什么

Pock 的核心定位在 README.md 中写得很清楚:

Widgets manager for MacBook's Touch Bar

它是一款免费、开源的工具,让你在「不放任何内容在屏幕上」的情况下,快速触达最常用的控件与服务。默认情况下,系统 Dock 占用了屏幕底部一条宝贵空间,而 Pock 将 Dock 等元素"移植"到 Touch Bar 中,配合"全宽"或"保留 Control Strip"两种布局,让屏幕真正回归内容本身。

从仓库的 Info.plist 可以看到,Pock 本身是一个 LSUIElement 为 true 的菜单栏型(Menu Bar-only)应用:它不占用 Dock 图标,主要通过菜单栏状态项(NSStatusBar)与 Touch Bar 交互,这与 AppDelegate.swift 中 mainBarItem / mainBarMenu 的实现完全对应。

二、安装 Pock

README 给出了最简单的三步安装流程:

  1. 前往 Pock 官方网站点击下载(pock_0_9_0__22.zip 之类的最新归档包)。
  2. 双击文件或运行 unzip 解压归档。
  3. 将解压得到的 Pock.app 拖入 /Applications。

注意:安装与运行 Pock 需要 macOS 10.15+(见 Podfile 的 platform :osx, '10.15'),且必须运行在带 Touch Bar 的 MacBook Pro 上。

三、使用入门

3.1 启动与菜单栏入口

安装完成后打开 Pock,随后:

  1. 检查菜单栏(Menu Bar):启动后会出现一个新的 Pock 图标(源码中由 AppDelegate.swift 使用 pock-inner-icon 模板图标创建)。
  2. 点击该图标即可看到 Pock 的主菜单,从中进入 Preferences…(偏好设置) 与 Manage Widgets…(管理 Widgets)。

菜单结构在 AppDelegate.swift 中完整定义,包含以下几组:

菜单分组 菜单项 快捷键
General About Pock –
General Preferences… ,
Widgets Manage widgets… m
Widgets Install widget… i
Customisation Customize Pock… p
Customisation Customize Control Strip… c
Advanced Re-install default widgets… w
Advanced Open widgets folder… f
Advanced Reload Pock… / Relaunch Pock… r / R
Advanced Reload Control Strip… / Relaunch Touch Bar… s / S
Advanced Show debug console… d
Goodbye Quit Pock q

如果启动后 Touch Bar 上没有出现 Pock,README 的提示是关键:

前往「系统偏好设置 → 键盘」,将「触控栏显示(Touch Bar shows)」设为 App Controls,然后重新启动 Pock。

这一步骤的本质原因可以从 TouchBarHelper.swift 中看到:Pock 依赖系统 Touch Bar 的 PresentationMode 设置(PresentationModeGlobal / com.apple.touchbar.agent),并通过 CFPreferences 读写系统控制条偏好,因此系统必须先允许 App Controls 呈现方式。

3.2 首次启动引导(On-Board)

首次启动时,Pock 会展示欢迎引导页(OnBoardViewController.swift),提示你"点击 Touch Bar 上的提示安装默认 Widgets"。Preferences<a href="https://link.gitcode.com/i/58160121fe4bfb934355a5dff9aa0283" target="_blank">.didShowOnBoard] 标记会在引导页加载后被置为 true,下次启动不再弹出([AppDelegate.swift)。

四、权限与隐私

4.1 系统权限建议

为了获得"无瑕疵的体验",README 建议阅读 Pock 官方文档中关于 Catalina(macOS 10.15)权限 的说明。在实际使用中,涉及的关键权限包括:

  • 辅助功能(Accessibility):Pock 需要观察全局键盘事件(如双击 ^Control 切换 Touch Bar,见 HotKey.swift 的 NSEvent.addGlobalMonitorForEvents)以及截取 Touch Bar 视图。
  • 屏幕录制(Screen Recording):某些 Touch Bar 视图抓取(snapshot)场景会触发系统授权提示。

4.2 匿名遥测说明

README 明确声明:Pock 会通过 AppCenter 发送一些匿名事件用于加速问题/Bug 的排查;这些事件绝不会用于营销目的(它不是一个商业软件包)。如果不认可这一点,请勿下载使用。

该声明在源码中得到印证:AppDelegate.swift 在 #if !DEBUG 分支下读取 Secrets.plist 中的 AppCenter 密钥并初始化 Analytics 与 Crashes 服务;各核心控制器(如 PreferencesViewController.swift)中散布着 Analytics.trackEvent(...) 调用。Debug 构建则不启用遥测,且 Roger.swift 的日志级别也会放宽。

五、卸载 Pock

  1. 退出 Pock(菜单栏图标 → Quit Pock,或快捷键 q)。
  2. 将 /Applications 中的 Pock.app 移到废纸篓。

如果卸载后 Touch Bar 没有恢复默认的系统控件,请前往「系统偏好设置 → 键盘」,选择 "Touch Bar shows App Controls",或按需配置系统设置。这是因为 Pock 卸载/退出时会通过 tearDownTouchBar() 恢复用户自定义的呈现模式(见 AppController.swift 与 AppDelegate.swift)。

六、内置 Widgets 详解

Pock 内置 五个默认 Widgets(Dock、Now Playing、ESC、Status、Control Center),另有 Weather 等更多 Widget 可扩展。源码层面,默认 Widget 通过 installDefaultWidgets() 从官方接口逐个下载安装(见 WidgetsInstaller.swift),并且全部安装在用户目录的 ~/Library/Application Support/Pock/Widgets/ 下(路径常量定义在 WidgetsLoader.swift)。

6.1 Dock widget —— 核心 Widget

你的 macOS Dock 被"搬进"了 Touch Bar,这是 Pock 的核心 Widget。它具备:

  • 完整的徽标(Badge)支持:不错过任何未读通知。
  • 多窗口支持:可以对同一 App 的多个窗口进行切换/展示。
  • 更多特性可在 Widget 设置与 Pock 偏好中配置。

它的价值正如 README 所说——每次都能享受全尺寸屏幕。

6.2 Now Playing widget

在 Touch Bar 上一览媒体信息,并内建媒体控制手势。README 给出了完整的手势表:

手势 动作
轻点(tap) 播放 / 暂停切换
向左轻扫(swipe left) 上一曲
向右轻扫(swipe right) 下一曲

6.3 ESC widget

Touch Bar 上常驻一个 ESC 按钮,当你不想隐藏 Pock 去调出系统 ESC 时,随时可以点按。

6.4 Status widget

时刻关注系统信息:当前时间、WiFi 状态、电池状态等。可在设置中配置要在 Status Widget 中展示哪些条目。

6.5 Control Center widget

在 Touch Bar 上调节屏幕亮度与系统音量。在 Control Center 条目上长按或滑动可唤出滑杆精细调节。

6.6 Weather widget

在 Touch Bar 中直接展示你所在位置的天气与预报,随时了解最新天气动态。仓库中 Special mentions 提到其数据服务使用了 openweather-proxy-rs 方案。

6.7 更多 Widgets

README 预告"更多 Widgets 即将到来"。同时,Pock 提供了一套完整的第三方 Widget 生态(见后文"为 Pock 开发自定义 Widget")。

实用提示:如果 Touch Bar 上一个 Widget 都没有,Pock 会在 Touch Bar 上显示"空状态"引导页(EmptyTouchBarController.swift),提示你 Tap to install default widgets… 或 Tap to add widgets to Pock…,一键进入默认 Widget 安装或自定义面板。

七、偏好设置(Preferences)

Pock 的偏好设置可从菜单栏的 Preferences… 与 Manage Widgets… 进入。底层由 Preferences.swift 的 Preferences 结构体统一读写 UserDefaults(个别项如"登录启动"走 LoginServiceKit)。全部设置键与默认值如下:

Keys 含义 默认值
allowBlankTouchBar 允许空 Touch Bar(移除全部 Widget 后 Touch Bar 可完全关闭) false
launchAtLogin 登录时自动启动 Pock false(依赖系统登录项)
layoutStyle 布局风格:withControlStrip / fullWidth withControlStrip
mouseSupportEnabled 启用光标(鼠标/触控板)支持 true
showTrackingArea 显示光标追踪区域(调试用途,蓝色高亮) false
checkForUpdatesOnceADay 每天自动检查一次更新 false
userDefinedPresentationMode 默认 Touch Bar 呈现模式 undefined(首次启动时记录系统当前值)
didShowOnBoard 是否已展示首次引导页 false
showDebugConsoleOnLaunch 启动时显示调试控制台 false

7.1 常规(General)

  • Allow blank Touch Bar:勾选后,你可以通过移除所有 Widget 让 Touch Bar 完全关闭。若不勾选,当 Widget 列表为空时,Pock 会自动显示"空状态"引导页(PockTouchBarController.swift)。
  • Launch at login:登录时自动启动。此选项由 LoginServiceKit 维护系统登录项(见 Preferences.swift 的 setter 分支)。

7.2 布局(Layout)

Pock 提供两种布局风格,对应 LayoutStyle 枚举:

  • Show Control Strip(保留 Control Strip):Pock 的 Touch Bar 与系统 Control Strip(亮度、音量、Siri 等系统控件区)并存。
  • Full width(全宽):Pock 独占整个 Touch Bar,最大化 Widget 空间。

两种布局在 Touch Bar 上的实际效果示意如下(资源来自仓库 Layout Styles 目录):

保留 Control Strip 的布局风格示意

全宽布局风格示意

源码层面,PockTouchBarController.present() 会根据布局风格决定 Touch Bar 的 placement 与系统 PresentationMode:

  • .withControlStrip → placement = 0、presentationMode = .appWithControlStrip
  • .fullWidth → placement = 1、presentationMode = .app

详见 PockTouchBarController.swift。

7.3 切换默认 Touch Bar 与呈现模式

  • 双击 ^Control 键即可在 Pock 与系统默认 Touch Bar 之间切换。这是通过 HotKey.swift 实现的"双击快捷键":全局监控 flagsChanged 事件,0.6 秒内连续两次按下 ^Control 才触发 toggleVisibility。
  • Default Touch Bar shows:可设置默认 Touch Bar 的呈现模式,可选项包括 App、App with Control Strip、Full Control Strip、Function Keys (Fn)、Workflows、Spaces 等(完整枚举见 TouchBarHelper.swift 的 PresentationMode)。设置会写入系统偏好 com.apple.touchbar.agent,并在 Pock 隐藏时恢复该模式。

温馨提示:偏好设置中会提示,为了正常工作 Pock 可能会覆盖系统默认 Touch Bar 偏好;你可以随时从「系统偏好设置 → 键盘」中重新配置。

7.4 光标选项(Cursor options)

  • Enable cursor support:启用后可用光标(触控板/鼠标)操作 Touch Bar 上的按钮与滑杆。Pock 通过 PKScreenEdgeController 在 Touch Bar 顶部边缘建立鼠标追踪区域,并将进入/移动/点击/滚动事件转发给各 Widget(PockTouchBarController.swift)。
  • Show tracking area:开发调试用,把追踪区域以蓝色高亮显示。

7.5 更新(Updates)

  • Check for updates once a day:勾选后每天自动检查一次更新。底层由 AppController.swift 的 prepareOnceADayTimer() 维护一个 24 小时周期定时器(首次触发在当天 11:20 后 24 小时)。
  • Check for updates:手动立即检查。若发现新版本会弹出升级确认框,确认后打开官方下载链接。

更新检查通过 Updater.swift 请求 https://pock.app/api/latestVersions.json(Debug 构建为 stage.pock.app),返回数据模型为 LatestReleases.swift 中的 core(Pock 本体版本)+ widgets(各 Widget 最新版本字典)。版本对象 Version.swift 包含 name、link、changelog 与可选的 core_min(要求的最低 Pock 版本,不满足时提示先升级 Pock)。

有新版本时,菜单栏的 Preferences… 与 Manage Widgets… 菜单项上会显示红色徽标(badge),提示核心或 Widget 有更新(AppDelegate.swift)。

八、自定义 Touch Bar 布局

从菜单栏选择 Customize Pock… 即可进入 macOS 原生的 Touch Bar 自定义面板(NSTouchBar Customization Palette):

  • 在自定义面板中,你可以调整 Widget 在 Touch Bar 中的顺序,并添加/移除 Widget。
  • 每个 Widget 在面板中显示为一张"快照"预览图,方便识别。该快照由 PKWidgetTouchBarItem.swift 生成:Widget 若实现 imageForCustomization 则直接使用自定义预览图,否则自动截取自身视图(NSButton 有特殊处理逻辑)作为预览。

实现链路如下:AppController.openPockCustomizationPalette() → 最小化 Pock 的 Touch Bar → 注册 NSTouchBarDidExitCustomization 通知 → NSApp.toggleTouchBarCustomizationPalette() → 退出自定义后重新呈现 Pock Touch Bar(AppController.swift)。

同理,Customize Control Strip… 会打开系统 Control Strip 的自定义面板(AppController.swift)。

九、Widgets 的安装、更新与卸载实战

9.1 Widget 的存储位置

所有 Widget 以 bundle(.pock) 形式存放在:

~/Library/Application Support/Pock/Widgets/

WidgetsLoader 启动时会扫描该目录(过滤掉 disabled 与带 / 的文件),逐个通过 PKWidgetInfo.swift 解析 Info.plist 元信息并加载(WidgetsLoader.swift)。

9.2 支持的安装格式

Pock 支持两种 Widget 包格式(WidgetsInstallViewController.swift):

格式 说明
.pock 单个 Widget bundle,直接复制到 Widgets 目录
.pkarchive Widget 归档包,解压后再安装内部 bundle

两种格式也都在 Info.plist 中注册为 Pock 的文档类型(CFBundleDocumentTypes),因此双击 .pock / .pkarchive 文件即可直接唤起 Pock 的安装流程(WidgetsInstaller 作为 NSDocument 子类接管处理)。

9.3 安装新 Widget

在菜单栏选择 Install widget…(快捷键 i)后,会出现安装面板:

  1. 直接将 .pock 或 .pkarchive 文件拖入面板,或点击 Choose… 从文件选择器选取。
  2. 确认后 Pock 将文件复制到 Widgets 目录并提示重载/重启 Pock 生效。

源码实现中,.pock 走 installWidget(widget:removeSource:),.pkarchive 走 extractAndInstall(name:atLocation:removeSource:)(使用 Zip 框架解压到临时目录再装回正式目录),详见 WidgetsInstaller.swift。

9.4 管理 Widget

打开 Manage widgets…(快捷键 m)进入 Widgets Manager(WidgetsManagerViewController.swift),列表会显示:

  • 每个 Widget 的加载状态(已加载/未加载)、名称、作者、版本。
  • 选中某个 Widget 后可执行 Update(更新)、Remove(卸载),若 Widget 自带偏好面板,还会在右侧内嵌展示该 Widget 的专属设置(PKWidgetPreference,含 Reset preferences 重置按钮)。
  • 顶部 Check for updates 按钮可手动刷新所有 Widget 的最新版本信息;有新版可用的 Widget 会在列表中显示更新徽标。

进阶:Advanced → Re-install default widgets…(w)可重新安装全部默认 Widget;Advanced → Open widgets folder…(f)会直接在 Finder 中打开 Widgets 目录(AppDelegate.swift),方便手动管理或排查。

9.5 更新与升级限制

更新 Widget 时,Updater.newVersion(for:) 会做两项检查(Updater.swift):

  1. 若新版 Widget 声明了 coreMin(最低 Pock 核心版本)且高于当前 Pock 版本,则拒绝更新并提示先升级 Pock。
  2. 仅当远程版本号高于本地版本时才给出更新入口。

更新面板会展示该版本附带的 Changelog,下载进度以进度条实时反馈(Downloader 基于 URLSessionDownloadTask 计算 bytesWritten / totalBytesExpectedToWrite,见 Downloader.swift)。

十、为 Pock 开发自定义 Widget(PockKit)

Pock 提供了名为 PockKit 的官方开发框架,用于构建自定义 Widget。从源码可以还原一个 .pock Widget bundle 的关键元数据约定(PKWidgetInfo.swift 的 BundleKeys):

Info.plist 键 含义 是否必需
CFBundleIdentifier Widget 唯一标识(决定 Touch Bar 项 identifier) 是
CFBundleDisplayName / CFBundleName 显示名称 是
CFBundleShortVersionString 版本号 是
CFBundleVersion 构建号(值为 1 时忽略) 可选
PKWidgetAuthor 作者 是
PKWidgetPreferenceClass 偏好设置控制器类名(实现 PKWidgetPreference) 可选
NSPrincipalClass Widget 主类(必须是 PKWidget 子类) 是

Widget 主类需要继承 PKWidget,并可选择性实现 viewWillAppear / viewDidAppear / viewWillDisappear / viewDidDisappear、imageForCustomization、prepareForCustomization、PKScreenEdgeMouseDelegate(鼠标支持)等生命周期与能力接口(见 PKWidgetViewController.swift 与 PKWidgetTouchBarItem.swift)。加载时,Pock 通过 bundle.principalClass 实例化 Widget 主类,并将其实例包装为 NSCustomTouchBarItem 插入 Touch Bar。

在 Podfile 中可以看到,Pock 本体通过 pod 'PockKit', :git => 'git@github.com:pock/pockkit.git' 依赖 PockKit;第三方开发者构建自定义 Widget 时则直接以 PockKit 为开发依赖。仓库中还带有 QLPockWidget(Quick Look 插件,PreviewViewController.swift)与 Relaunch(重启辅助程序,main.swift)两个辅助 Target,分别用于快速预览 .pock 包和在更新/安装后自动重启 Pock(AppController.relaunch(),见 AppController.swift)。

十一、参与贡献与依赖

第三方依赖(见 Podfile 与 README.md):

  • PockKit:Pock 的核心 Widget 框架。
  • AppCenter / AppCenter-Crashes:匿名遥测与崩溃收集。
  • Magnet:全局快捷键支持。
  • Zip:.pkarchive 归档解压。
  • TinyConstraints:Auto Layout 便捷约束。

十二、总结

Pock 的价值在于让 Touch Bar 从"系统固定的几个按键"变成完全由你掌控的可扩展面板:内置的 Dock、Now Playing、ESC、Status、Control Center 与 Weather Widget 覆盖了高频需求;偏好设置提供了布局、呈现模式、光标支持与更新策略的精细控制;而 PockKit 则向开发者开放了完整的自定义 Widget 生态。通过阅读本仓库源码(入口建议从 AppDelegate.swift → AppController.swift → PockTouchBarController.swift 沿调用链展开),无论是普通用户排查问题,还是开发者构建自己的 Touch Bar Widget,都能获得清晰的工程指引。

登录后查看全文
pock