由于只有 1 台显示器,经常需要切换不同的输入源,在显示器上切换很麻烦,于是开始研究是否可以实现自动切换。
由于本人只需要在 mac 下使用,故仅记录了 mac 的内容。
前提条件:
- 显示器支持 DDC/CI 协议
命令行切换
Mac下有两个工具可以使用,详细的区别可参考这里
用法示例:
ddcctl -d 1 -i 15
m1ddc display {uuid} set input 15
快捷键切换
命令行足够轻量级,却不够方便,我们可以使用 mac 自带的 Automator 添加快捷键。步骤如下:
打开 Automator,选择「快速操作」
![longshot20241128172303.png]()
填写切换显示器命令
![longshot20241128172506.png=600x]()
保存
![longshot20241128172544.png=600x]()
在系统中配置键盘快捷键
![longshot20241128172625.png=600x]()
唤醒时自动切换输入源
唤醒时,自动切换显示器,需要用到 sleepwatcher
2026.04.07 更新: 建议使用 hammerspoon 了,事件更丰富,定制更灵活
brew install sleepwatcher
brew services start sleepwatcher
唤醒和睡眠时会分别执行 ~/.wakeup 和 ~/.sleep,新建文件如下
touch ~/.wakeup
chmod 755 ~/.wakeup
在 .wakeup 中写入要执行的命令即可。
这里尝试基于 m1ddc 写了脚本,供参考。ddcctl 获取当前输入源会失败,直接写入切换命令就好了。
#!/bin/bash
m1ddc() {
/usr/local/bin/m1ddc $@
}
switch_input_source() {
local monitor_uuid=$1
local monitor_input=$2
if [ $(m1ddc display list | grep -c $monitor_uuid) -eq 1 ]; then
currentInput=$(m1ddc display $monitor_uuid get input)
if [ $currentInput == $monitor_input ]; then
echo "无需切换"
else
echo "需要切换"
m1ddc display $monitor_uuid set input $monitor_input
fi
fi
}
# 指定显示器
switch_input_source "C315CEDD-8D5B-4F19-A7F0-A88CEB9CEC21" 15
遗留问题
1, 若当前输入源正确,重新执行切换会闪烁
m1ddc 可以获取当前输入源,可以写逻辑解决,ddcctl 则不行
2026.04.07 更新: 实际是因为 macOS 使用 HDMI 连接时,对 DCC 协议支持不完善导致,换成 DP 线则正常
2, 唤醒其实不是一个准确的事件,比如合盖然后开盖可能不会触发,目前没有找到轻量级的方案。
2026.04.07 更新: 可以通过 hammerspoon 实现开盖检测,参考 AI 给出的触发代码 ~/.hammerspoon/init.lua
local function triggerSwitch()
-- hs.alert.show("✅ 硬件级判定:已开盖,执行切换!")
-- hs.execute("/bin/bash switch-monitor.sh")
end
-- =====================================================================
-- 辅助函数:通过 ioreg 真正读取物理盖子的开合状态
-- 返回 true 表示盖子是开着的,false 表示合盖
-- =====================================================================
local function isLidOpen()
-- 执行底层的 ioreg 命令
local output, status, type, rc = hs.execute("ioreg -r -k AppleClamshellState -d 4 | grep AppleClamshellState")
-- 如果输出里包含 "No",说明 AppleClamshellState = No (即没合盖)
if string.find(output, "No") then
return true
else
return false
end
end
-- =====================================================================
-- 监听器:结合底层硬件状态的精确拦截
-- =====================================================================
-- 记录上一次探测到的物理状态
local wasLidOpen = isLidOpen()
local function exactScreenCallback()
-- 屏幕状态发生任何变化时,去读一下真实的物理盖子传感器
local currentlyOpen = isLidOpen()
-- 核心逻辑:只有当“之前是合盖”且“现在是开盖”时,才触发!
-- 这样插拔其他外接显示器绝对不会引起误触发。
if (not wasLidOpen) and currentlyOpen then
print("探测到物理开盖动作")
triggerSwitch()
end
-- 更新状态记录
wasLidOpen = currentlyOpen
end
-- screen.watcher 作为触发“钩子”,但用硬件状态做“校验”
screenWatcher = hs.screen.watcher.new(exactScreenCallback)
screenWatcher:start()
本文链接:https://blog.xiaoyuyu.cn/post/mac-switch-monitor-input-source.html,参与评论 »
--EOF--
发表于 2024-11-28 17:39:00。
本站使用「署名 4.0 国际」创作共享协议,转载请注明作者及原网址。更多说明 »
提醒:本文最后更新于 502 天前,文中所描述的信息可能已发生改变,请谨慎使用。




Comments