Skip to content

Instantly share code, notes, and snippets.

@khanhicetea
Last active March 10, 2026 09:11
Show Gist options
  • Select an option

  • Save khanhicetea/534ec96ad97171285fad6973504fab66 to your computer and use it in GitHub Desktop.

Select an option

Save khanhicetea/534ec96ad97171285fad6973504fab66 to your computer and use it in GitHub Desktop.
Auto Display MacOS

The python script is has auto mode for detecting the external monitors connected so it softly turn-off Builtin Monitor without closing lid. Then it detects when user un-plugged all externals from Macbook then turn on the Builtin Monitor back

Usage :

Auto detection mode

python3 display.py auto

Manual mode:

$ python3 display.py list
$ python3 display.py on [ID]
$ python3 display.py off [ID]
#!/usr/bin/env python3
import subprocess
import sys
import time
from ctypes import CDLL, POINTER, byref, c_bool, c_int, c_uint32, c_void_p, util
# --- Framework Setup ---
# Use absolute paths for stability on some macOS environments
cg_path = util.find_library("CoreGraphics")
if not cg_path:
cg_path = "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics"
cg = CDLL(cg_path)
# CoreGraphics Bindings with explicit error checking
cg.CGBeginDisplayConfiguration.argtypes = [POINTER(c_void_p)]
cg.CGCompleteDisplayConfiguration.argtypes = [c_void_p, c_int]
cg.CGSConfigureDisplayEnabled.argtypes = [c_void_p, c_uint32, c_bool]
cg.CGGetActiveDisplayList.argtypes = [c_uint32, POINTER(c_uint32), POINTER(c_uint32)]
cg.CGGetOnlineDisplayList.argtypes = [c_uint32, POINTER(c_uint32), POINTER(c_uint32)]
cg.CGDisplayIsBuiltin.restype = c_bool
cg.CGDisplayIsBuiltin.argtypes = [c_uint32]
# For resolution - using simplified calls to avoid mode-copy crashes
cg.CGDisplayPixelsWide.argtypes = [c_uint32]
cg.CGDisplayPixelsWide.restype = c_int
cg.CGDisplayPixelsHigh.argtypes = [c_uint32]
cg.CGDisplayPixelsHigh.restype = c_int
# Dynamic timeout
timeout = 30
def get_display_basic_info(display_id):
"""Fetches info using safe, direct calls instead of Mode pointers."""
try:
w = cg.CGDisplayPixelsWide(display_id)
h = cg.CGDisplayPixelsHigh(display_id)
is_builtin = bool(cg.CGDisplayIsBuiltin(display_id))
name = "Built-in" if is_builtin else "External"
return name, f"{w}x{h}", is_builtin
except Exception:
return "Unknown", "Unknown", False
def get_active_ids():
max_displays = 16
count = c_uint32()
ids = (c_uint32 * max_displays)()
if cg.CGGetActiveDisplayList(max_displays, ids, byref(count)) == 0:
return [ids[i] for i in range(count.value)]
return []
def get_online_ids():
max_displays = 16
count = c_uint32()
ids = (c_uint32 * max_displays)()
if cg.CGGetOnlineDisplayList(max_displays, ids, byref(count)) == 0:
return [ids[i] for i in range(count.value)]
return []
def set_state(display_id, state):
config_ref = c_void_p()
if cg.CGBeginDisplayConfiguration(byref(config_ref)) == 0:
# CGSConfigureDisplayEnabled is a private API,
# return code 0 means success
res = cg.CGSConfigureDisplayEnabled(config_ref, display_id, state)
cg.CGCompleteDisplayConfiguration(config_ref, 0)
return res == 0
return False
def profiler_only_1080p_fhd():
"""Fallback detector for stale active display IDs after unplug events."""
try:
output = subprocess.check_output(
["system_profiler", "SPDisplaysDataType"],
text=True,
stderr=subprocess.DEVNULL,
)
except Exception:
return False
resolution_lines = []
for line in output.splitlines():
stripped = line.strip()
if stripped.startswith("Resolution:"):
resolution_lines.append(stripped)
return len(resolution_lines) == 1 and "1080p FHD" in resolution_lines[0]
def get_profiler_display_counts():
"""Returns (internal_count, external_count) parsed from system_profiler."""
try:
output = subprocess.check_output(
["system_profiler", "SPDisplaysDataType", "-detailLevel", "mini"],
text=True,
stderr=subprocess.DEVNULL,
timeout=8,
)
except Exception:
return 0, 0
def flush_record(block_lines, counts):
if not block_lines:
return
block = "\n".join(block_lines).lower()
is_internal = (
"connection type: internal" in block
or "display type: built-in" in block
or "display type: built in" in block
)
if is_internal:
counts["internal"] += 1
else:
counts["external"] += 1
counts = {"internal": 0, "external": 0}
in_displays = False
displays_indent = -1
current_block = []
have_name = False
for line in output.splitlines():
indent = len(line) - len(line.lstrip())
stripped = line.strip()
if not stripped:
continue
if stripped.lower() == "displays:":
flush_record(current_block, counts)
in_displays = True
displays_indent = indent
current_block = []
have_name = False
continue
if not in_displays:
continue
# End of Displays section.
if indent <= displays_indent:
flush_record(current_block, counts)
in_displays = False
current_block = []
have_name = False
continue
# Start of a display record "<name>:"
if line.rstrip().endswith(":") and indent == displays_indent + 2:
flush_record(current_block, counts)
current_block = []
have_name = True
continue
if have_name and indent > displays_indent + 2:
current_block.append(stripped)
flush_record(current_block, counts)
return counts["internal"], counts["external"]
# --- CLI Handlers ---
def run_list():
ids = get_active_ids()
if not ids:
print("No active displays found.")
return
print(f"\n{'ID':<15} | {'Type':<12} | {'Resolution':<12}")
print("-" * 45)
for d_id in ids:
name, res, _ = get_display_basic_info(d_id)
print(f"{d_id:<15} | {name:<12} | {res:<12}")
def run_auto():
print("🚀 Auto-Mode Active. (Ctrl+C to stop)")
disabled_set = set()
try:
while True:
active_ids = get_active_ids()
online_ids = get_online_ids()
print(
f"[{time.strftime('%H:%M:%S')}] [DEBUG] Active IDs: "
f"{', '.join(str(d_id) for d_id in active_ids) if active_ids else '(none)'} | "
f"Online IDs: {', '.join(str(d_id) for d_id in online_ids) if online_ids else '(none)'}"
)
current_builtins = []
detection_ids = online_ids if online_ids else active_ids
has_external_connected_cg = False
for d_id in active_ids:
name, res, is_builtin = get_display_basic_info(d_id)
print(f"\t- {d_id:<15} | {name:<12} | {res:<12}")
if is_builtin:
current_builtins.append(d_id)
for d_id in detection_ids:
_, _, is_builtin = get_display_basic_info(d_id)
if not is_builtin:
has_external_connected_cg = True
break
profiler_internal_count, profiler_external_count = (
get_profiler_display_counts()
)
has_external_connected_profiler = profiler_external_count > 0
has_external_connected = (
has_external_connected_cg or has_external_connected_profiler
)
print(
f"[{time.strftime('%H:%M:%S')}] [DEBUG] Built-ins: "
f"{', '.join(str(d_id) for d_id in current_builtins) if current_builtins else '(none)'} | "
f"External connected: {has_external_connected} "
f"(cg={has_external_connected_cg}, profiler={has_external_connected_profiler}, "
f"profiler counts i={profiler_internal_count}/e={profiler_external_count}) | "
f"Tracked disabled IDs: {', '.join(str(d_id) for d_id in sorted(disabled_set)) if disabled_set else '(none)'}"
)
profiler_restore_signal = bool(disabled_set) and profiler_only_1080p_fhd()
restore_needed = bool(disabled_set) and (
(not has_external_connected) or profiler_restore_signal
)
# Logic: If external detected, turn off built-ins
if has_external_connected and current_builtins:
for b_id in current_builtins:
timeout = 5
if set_state(b_id, False):
disabled_set.add(b_id)
print(
f"[{time.strftime('%H:%M:%S')}] External detected -> Disabling Internal ({b_id})"
)
# Logic: If no external, restore
elif restore_needed:
print(
f"[{time.strftime('%H:%M:%S')}] External removed -> Restoring Internal..."
)
for b_id in list(disabled_set):
set_state(b_id, True)
disabled_set.clear()
timeout = 30
print(
f"[{time.strftime('%H:%M:%S')}] [DEBUG] Tracked disabled IDs after restore: (none)"
)
time.sleep(timeout) # Faster response time
except KeyboardInterrupt:
print("\nStopping... Restoring screens.")
for b_id in list(disabled_set):
set_state(b_id, True)
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python3 display.py [list | on <id> | off <id> | auto]")
sys.exit(0)
cmd = sys.argv[1].lower()
if cmd == "list":
run_list()
elif cmd == "auto":
run_auto()
elif cmd in ["on", "off"] and len(sys.argv) == 3:
target = int(sys.argv[2])
if set_state(target, cmd == "on"):
print(f"Successfully turned {cmd.upper()} display {target}")
else:
print(f"Failed to turn {cmd.upper()} display {target}")
else:
print("Invalid command.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment