"""Clipboard image extraction for macOS and Linux. Provides a single function `save_clipboard_image(dest)` that checks the system clipboard for image data, saves it to *dest* as PNG, and returns True on success. No external Python dependencies — uses only OS-level CLI tools that ship with the platform (or are commonly installed). Platform support: macOS — osascript (always available), pngpaste (if installed) Linux — xclip (apt install xclip) """ import logging import subprocess import sys from pathlib import Path logger = logging.getLogger(__name__) def save_clipboard_image(dest: Path) -> bool: """Extract an image from the system clipboard and save it as PNG. Returns True if an image was found and saved, False otherwise. """ dest.parent.mkdir(parents=True, exist_ok=True) if sys.platform == "darwin": return _macos_save(dest) return _linux_save(dest) # ── macOS ──────────────────────────────────────────────────────────────── def _macos_save(dest: Path) -> bool: """Try pngpaste first (fast, handles more formats), fall back to osascript.""" return _macos_pngpaste(dest) or _macos_osascript(dest) def _macos_pngpaste(dest: Path) -> bool: """Use pngpaste (brew install pngpaste) — fastest, cleanest.""" try: r = subprocess.run( ["pngpaste", str(dest)], capture_output=True, timeout=3, ) if r.returncode == 0 and dest.exists() and dest.stat().st_size > 0: return True except FileNotFoundError: pass # pngpaste not installed except Exception as e: logger.debug("pngpaste failed: %s", e) return False def _macos_osascript(dest: Path) -> bool: """Use osascript to extract PNG data from clipboard (always available).""" # First check if clipboard contains image data try: info = subprocess.run( ["osascript", "-e", "clipboard info"], capture_output=True, text=True, timeout=3, ) has_image = "«class PNGf»" in info.stdout or "«class TIFF»" in info.stdout if not has_image: return False except Exception: return False # Extract as PNG script = ( 'try\n' ' set imgData to the clipboard as «class PNGf»\n' f' set f to open for access POSIX file "{dest}" with write permission\n' ' write imgData to f\n' ' close access f\n' 'on error\n' ' return "fail"\n' 'end try\n' ) try: r = subprocess.run( ["osascript", "-e", script], capture_output=True, text=True, timeout=5, ) if r.returncode == 0 and "fail" not in r.stdout and dest.exists() and dest.stat().st_size > 0: return True except Exception as e: logger.debug("osascript clipboard extract failed: %s", e) return False # ── Linux ──────────────────────────────────────────────────────────────── def _linux_save(dest: Path) -> bool: """Use xclip to extract clipboard image.""" # Check if clipboard has image content try: targets = subprocess.run( ["xclip", "-selection", "clipboard", "-t", "TARGETS", "-o"], capture_output=True, text=True, timeout=3, ) if "image/png" not in targets.stdout: return False except FileNotFoundError: logger.debug("xclip not installed — clipboard image paste unavailable") return False except Exception: return False # Extract PNG data try: with open(dest, "wb") as f: subprocess.run( ["xclip", "-selection", "clipboard", "-t", "image/png", "-o"], stdout=f, stderr=subprocess.DEVNULL, timeout=5, check=True, ) if dest.exists() and dest.stat().st_size > 0: return True except Exception as e: logger.debug("xclip image extraction failed: %s", e) dest.unlink(missing_ok=True) return False