"""A wrapper around screeninfo with improved functionality on macOS."""
import sys
from typing import Iterable, List, Optional, Tuple
import screeninfo
from screeninfo import Monitor
[docs]def get_monitors() -> List[Monitor]:
"""Return a list of Monitor objects representing the connected screens."""
if sys.platform == "darwin":
return list(_enumerate_macos_monitors())
return screeninfo.get_monitors()
[docs]def get_ppmm(monitor: Monitor) -> Optional[Tuple[float, float]]:
"""Return the pixels per millimeter of the given monitor."""
if not monitor.width_mm or not monitor.height_mm:
return None
return (monitor.width / monitor.width_mm, monitor.height / monitor.height_mm)
def _enumerate_macos_monitors() -> Iterable[Monitor]:
# isort: off
from AppKit import ( # pyright: ignore[reportMissingImports]
NSDeviceSize, # pyright: ignore[reportGeneralTypeIssues]
NSScreen, # pyright: ignore[reportGeneralTypeIssues]
)
from Quartz import ( # pyright: ignore[reportMissingImports]
CGDisplayScreenSize, # pyright: ignore[reportGeneralTypeIssues]
)
# isort: on
screens = NSScreen.screens()
for screen in screens:
f = screen.frame
if callable(f):
f = f()
description = screen.deviceDescription()
width, height = description[NSDeviceSize].sizeValue()
width_mm, height_mm = CGDisplayScreenSize(description["NSScreenNumber"])
yield Monitor(
x=int(f.origin.x),
y=int(f.origin.y),
width=width,
height=height,
width_mm=width_mm,
height_mm=height_mm,
is_primary=(screen == screens[0]),
)