feat: native clipboard image sync (Linux, opt-in sync_images)

This commit is contained in:
2026-08-14 09:51:25 -04:00
parent 884415c1c1
commit 147cba6d2a
15 changed files with 274 additions and 48 deletions
+18
View File
@@ -8,6 +8,12 @@
// Each platform file defines its own New() constructor using //go:build tags.
package clipboard
import "errors"
// ErrNoImage is returned by ImageClipboard.ReadImage when the clipboard holds
// no image data. It is a normal condition, not an error.
var ErrNoImage = errors.New("clipboard: no image")
// Clipboard is the cross-platform clipboard interface.
type Clipboard interface {
// Read returns the current text content of the clipboard.
@@ -17,3 +23,15 @@ type Clipboard interface {
// Write sets the clipboard text content.
Write(text string) error
}
// ImageClipboard is an optional interface implemented by platforms that can
// read and write image data from the clipboard. Use a type assertion to detect
// support: `if ic, ok := cb.(clipboard.ImageClipboard); ok { ... }`.
type ImageClipboard interface {
// ReadImage returns the MIME type and raw bytes of the clipboard image.
// It returns ErrNoImage if the clipboard holds no image.
ReadImage() (mime string, data []byte, err error)
// WriteImage sets the clipboard image content.
WriteImage(mime string, data []byte) error
}
+35
View File
@@ -3,6 +3,7 @@
package clipboard
import (
"bytes"
"fmt"
"os"
"os/exec"
@@ -70,3 +71,37 @@ func (c *linuxClipboard) Write(text string) error {
}
return nil
}
// ReadImage returns the PNG image from the clipboard, if any.
func (c *linuxClipboard) ReadImage() (string, []byte, error) {
var args []string
if c.pasteCmd == "wl-paste" {
args = []string{"--type", "image/png"}
} else {
args = []string{"-selection", "clipboard", "-t", "image/png", "-o"}
}
cmd := exec.Command(c.pasteCmd, args...)
out, err := cmd.Output()
if err != nil || len(out) == 0 {
return "", nil, ErrNoImage
}
return "image/png", out, nil
}
// WriteImage writes image bytes to the clipboard using the given MIME type.
func (c *linuxClipboard) WriteImage(mime string, data []byte) error {
var args []string
if c.copyCmd == "wl-copy" {
args = []string{"--type", mime}
} else {
args = []string{"-selection", "clipboard", "-t", mime}
}
cmd := exec.Command(c.copyCmd, args...)
cmd.Stdin = bytes.NewReader(data)
if err := cmd.Run(); err != nil {
return fmt.Errorf("clipboard write image (%s): %w", c.copyCmd, err)
}
return nil
}