feat: Windows (CF_DIB) and macOS (AppleScript) clipboard image sync

This commit is contained in:
2026-08-14 09:55:32 -04:00
parent 147cba6d2a
commit 32eff914d5
10 changed files with 334 additions and 7 deletions
+53
View File
@@ -4,6 +4,7 @@ package clipboard
import (
"fmt"
"os"
"os/exec"
"strings"
)
@@ -43,3 +44,55 @@ func (c *darwinClipboard) Write(text string) error {
}
return nil
}
// ReadImage reads a PNG image from the clipboard via AppleScript, writing it to
// a temporary file and reading it back.
func (c *darwinClipboard) ReadImage() (string, []byte, error) {
tmp, err := os.CreateTemp("", "clip-sync-*.png")
if err != nil {
return "", nil, err
}
tmpPath := tmp.Name()
tmp.Close()
defer os.Remove(tmpPath)
// AppleScript type code PNGf, wrapped in the chevron quotes AppleScript uses.
script := `set f to (open for access POSIX file "` + tmpPath + `" with write permission)
set eof f to 0
write (the clipboard as «class PNGf») to f
close access f`
if err := exec.Command("osascript", "-e", script).Run(); err != nil {
return "", nil, ErrNoImage
}
data, err := os.ReadFile(tmpPath)
if err != nil || len(data) == 0 {
return "", nil, ErrNoImage
}
return "image/png", data, nil
}
// WriteImage writes a PNG image to the clipboard via AppleScript.
func (c *darwinClipboard) WriteImage(mime string, data []byte) error {
if mime != "" && mime != "image/png" {
return fmt.Errorf("clipboard: unsupported image mime %q (only PNG)", mime)
}
tmp, err := os.CreateTemp("", "clip-sync-*.png")
if err != nil {
return err
}
if _, err := tmp.Write(data); err != nil {
tmp.Close()
os.Remove(tmp.Name())
return err
}
tmpPath := tmp.Name()
tmp.Close()
defer os.Remove(tmpPath)
script := `set the clipboard to (read (POSIX file "` + tmpPath + `") as «class PNGf»)`
if err := exec.Command("osascript", "-e", script).Run(); err != nil {
return fmt.Errorf("clipboard write image (osascript): %w", err)
}
return nil
}