Macbook Pro 用外接显示器时,如何关闭笔记本屏幕,同时开盖使用?
macos 提供了一些 私有 API,可以获得当前插入的显示器中,是否同时包含内建显示器和外部显示器,并关闭/启动 内建显示器。
其中,可能用到的 API:(仅限 apple silicon,intel 未知)
CGGetActiveDisplayList
CGDisplayIsBuiltin
CGBeginDisplayConfiguration
CGSConfigureDisplayEnabled
CGSCompleteDisplayConfiguration我用 vibe coding 写了一个 python 脚本(deepseek v4 pro 就够了)大家也可以 vibe coding 生成一下:
提示词:
完成一个 python 脚本,功能:
1. 如果系统不是 macos,报错退出
2. 如果处理器不是 apple silicon,报错退出
3. 获取显示器列表,如果仅包含内建显示器,无连接的外部显示器,则强制开启内建显示器
4. 如果同时包含内建显示器和外部显示器,则 toggle 内建显示器的开关状态,进行 toggle 前要通过交互提示用户是否确认;
以下为可能用到的公有和私有 API:
CGGetActiveDisplayList
CGDisplayIsBuiltin
CGBeginDisplayConfiguration
CGSConfigureDisplayEnabled
CGSCompleteDisplayConfiguration
脚本内容(不保证效果,仅支持 apple silicon 处理器):
#!/usr/bin/env python3
"""Toggle built-in display on/off via CoreGraphics private API.
Minimal script for Karabiner-Elements keybinding. Apple Silicon only."""
import sys
import os
import ctypes
if sys.platform != "darwin":
print(f"ERROR: macOS only. Current: {sys.platform}", file=sys.stderr)
sys.exit(1)
if os.uname().machine != "arm64":
print(f"ERROR: Apple Silicon only. Current: {os.uname().machine}", file=sys.stderr)
sys.exit(1)
libc = ctypes.CDLL('/usr/lib/libSystem.dylib')
libc.dlopen.argtypes = [ctypes.c_char_p, ctypes.c_int]
libc.dlopen.restype = ctypes.c_void_p
libc.dlsym.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
libc.dlsym.restype = ctypes.c_void_p
_cgs_handle = libc.dlopen(
b'/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics', 1)
if not _cgs_handle:
print("ERROR: Cannot load CoreGraphics framework.", file=sys.stderr)
sys.exit(1)
def _lookup(name: str):
name_bytes = name.encode()
ptr = libc.dlsym(_cgs_handle, name_bytes)
if not ptr:
ptr = libc.dlsym(ctypes.c_void_p(-2), name_bytes)
if not ptr:
print(f"ERROR: symbol `{name}` not found.", file=sys.stderr)
sys.exit(1)
return ptr
MAX_DISPLAYS = 64
CGSGetDisplayList = ctypes.CFUNCTYPE(
ctypes.c_int32, ctypes.c_uint32,
ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint32),
)(_lookup('CGSGetDisplayList'))
CGGetActiveDisplayList = ctypes.CFUNCTYPE(
ctypes.c_int32, ctypes.c_uint32,
ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint32),
)(_lookup('CGGetActiveDisplayList'))
CGDisplayIsBuiltin = ctypes.CFUNCTYPE(ctypes.c_int32, ctypes.c_uint32)(
_lookup('CGDisplayIsBuiltin'))
CGBeginDisplayConfiguration = ctypes.CFUNCTYPE(
ctypes.c_int32, ctypes.POINTER(ctypes.c_void_p),
)(_lookup('CGBeginDisplayConfiguration'))
CGSConfigureDisplayEnabled = ctypes.CFUNCTYPE(
ctypes.c_int32, ctypes.c_void_p, ctypes.c_uint32, ctypes.c_bool,
)(_lookup('CGSConfigureDisplayEnabled'))
CGSCompleteDisplayConfiguration = ctypes.CFUNCTYPE(
ctypes.c_int32, ctypes.c_void_p,
)(_lookup('CGSCompleteDisplayConfiguration'))
def _get_all_displays():
ids = (ctypes.c_uint32 * MAX_DISPLAYS)()
count = ctypes.c_uint32(0)
CGSGetDisplayList(MAX_DISPLAYS, ids, ctypes.byref(count))
return [ids[i] for i in range(count.value)]
def _get_active_displays():
ids = (ctypes.c_uint32 * MAX_DISPLAYS)()
count = ctypes.c_uint32(0)
CGGetActiveDisplayList(MAX_DISPLAYS, ids, ctypes.byref(count))
return {ids[i] for i in range(count.value)}
def _find_builtin(displays):
for did in displays:
if CGDisplayIsBuiltin(did):
return did
return None
def main():
displays = _get_all_displays()
builtin_id = _find_builtin(displays)
if builtin_id is None:
print("No built-in display found.", file=sys.stderr)
sys.exit(1)
active_set = _get_active_displays()
builtin_active = builtin_id in active_set
external_active_count = sum(
1 for did in displays if did != builtin_id and did in active_set)
if external_active_count == 0 and builtin_active:
print("Built-in is the only active display. Refusing to disable.",
file=sys.stderr)
sys.exit(1)
target = not builtin_active
config = ctypes.c_void_p(0)
if CGBeginDisplayConfiguration(ctypes.byref(config)) != 0:
print("CGBeginDisplayConfiguration failed.", file=sys.stderr)
sys.exit(1)
if CGSConfigureDisplayEnabled(config, builtin_id, target) != 0:
print("CGSConfigureDisplayEnabled failed.", file=sys.stderr)
sys.exit(1)
if CGSCompleteDisplayConfiguration(config) != 0:
print("CGSCompleteDisplayConfiguration failed.", file=sys.stderr)
sys.exit(1)
action = "enabled" if target else "disabled"
print(f"Built-in display {action}.")
if __name__ == "__main__":
main()编辑于 2026-06-04 · 著作权归作者所有