Files
2026-04-21 23:38:29 +08:00

87 lines
3.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
import shutil
import subprocess
import sys
import time
from pathlib import Path
from .config import ScreenshotCfg
class ScreenshotCapture:
def __init__(self, cfg: ScreenshotCfg):
self._cfg = cfg
def capture(self) -> str:
"""截取全屏,返回保存路径。自动选择当前平台最佳方式。"""
if self._cfg.delay_ms > 0:
time.sleep(self._cfg.delay_ms / 1000)
out_path = self._cfg.tmp_path
Path(out_path).parent.mkdir(parents=True, exist_ok=True)
if sys.platform == "darwin":
self._capture_macos(out_path)
else:
self._capture_linux(out_path)
if not Path(out_path).exists():
raise RuntimeError(f"截图文件未生成: {out_path}")
return out_path
# ------------------------------------------------------------------
# macOS
# ------------------------------------------------------------------
def _capture_macos(self, out_path: str) -> None:
# screencapture -x 静默截全屏(无声音/闪烁)
subprocess.run(["screencapture", "-x", out_path], check=True)
# ------------------------------------------------------------------
# Linux(按优先级尝试)
# ------------------------------------------------------------------
def _capture_linux(self, out_path: str) -> None:
wayland = os.environ.get("WAYLAND_DISPLAY")
if wayland:
# Wayland 优先:grim(轻量)> spectacle > gnome-screenshot
if shutil.which("grim"):
subprocess.run(["grim", out_path], check=True)
return
if shutil.which("spectacle"):
# spectacle -b 后台 -f 全屏 -n 无通知 -o 输出路径
# 丢弃 stderrTesseract 未安装的无害警告)
subprocess.run(
["spectacle", "-b", "-f", "-n", "-o", out_path],
check=True,
timeout=10,
stderr=subprocess.DEVNULL,
)
return
if shutil.which("gnome-screenshot"):
subprocess.run(["gnome-screenshot", "-f", out_path], check=True)
return
# 最后尝试 mss(可能在 XWayland 下有效)
self._capture_mss(out_path)
else:
# X11mss 最快,失败则用 scrot
try:
self._capture_mss(out_path)
except Exception:
if shutil.which("scrot"):
subprocess.run(["scrot", out_path], check=True)
elif shutil.which("import"): # ImageMagick
subprocess.run(["import", "-window", "root", out_path], check=True)
else:
raise RuntimeError("未找到可用的截图工具(scrot / import")
def _capture_mss(self, out_path: str) -> None:
import mss
import mss.tools
with mss.mss() as sct:
monitor = sct.monitors[0] # 0 = 全部显示器合并
screenshot = sct.grab(monitor)
mss.tools.to_png(screenshot.rgb, screenshot.size, output=out_path)