使用前必须先调用一次 clipboard.Init(),无显示环境会返回错误;Linux/BSD 上程序退出后自己写入的剪贴板数据随之消失,需保持进程运行;Loops 自动清除仅在 X11/Wayland 生效,Windows 和 macOS 上会被静默忽略。
clipboard
golang-designMIT活跃维护Go 语言跨平台剪贴板库,支持在 macOS、Linux、Windows、Android 和 iOS 上读写文本与图片。
📋 cross-platform clipboard package that supports accessing text and image in Go (macOS/Linux/Windows/Android/iOS)
go install golang.design/x/clipboard/cmd/gclip@latestREADME 未说明显存或 GPU 要求;桌面端无需 Cgo 和图形库依赖,但 Linux/BSD 运行时需要 Wayland 合成器(支持 data-control)或 X server,无显示环境(服务器、CI)需启动 Xvfb 虚拟 X 服务器。
Go 跨平台剪贴板库,统一读写文本、图片、文件和自定义 MIME 类型
Go 语言跨平台剪贴板库,支持在 macOS、Linux、Windows、Android 和 iOS 上读写文本与图片。
核心能力
- 桌面端无需 Cgo,不用 C 编译器和 libX11/libwayland
- 支持文本、PNG 图片、文件及自定义 MIME 类型读写
- 用 WriteAll 一次写入多种格式,粘贴时由应用择优
- 用 Watch 监听剪贴板变化,用 Loops 控制粘贴后自动清除
- Linux 自动在 Wayland 与 X11 间切换,无需配置
容易踩的坑
- v0.11.0最新正式版2026-09-26 · 2026-09-26 10:45 UTC
Tells you when a copy came from a password manager, so a clipboard manager, a history, or a sync tool can leave it alone. No breaking changes:
go get golang.design/x/[email protected].New
SensitiveandData.Sensitive(#178, #179). Password managers mark the passwords they copy, but this package couldn't see those marks, becauseFormatsonly reports MIME-shaped types. So a tool built onWatchsynced every password its user copied. Now:for data := range clipboard.Watch(ctx, clipboard.FmtText) { if data.Sensitive { continue // a password: don't store or upload it } save(data.Bytes) }clipboard.Sensitive(ctx)answers the same question for the current content.Platform Mark read macOS org.nspasteboard.ConcealedType,org.nspasteboard.TransientTypeWindows ExcludeClipboardContentFromMonitorProcessing;CanIncludeInClipboardHistoryorCanUploadToCloudClipboardset to 0X11, Wayland x-kde-passwordManagerHintOn iOS, Android and in the browser there's no mark to read, so
SensitivereturnsErrUnsupported, never afalsethat looks like "safe". Checking for the mark isn't a paste, so it doesn't count against aLoopslimit.Fixed
- The README's CI badge showed "no status" (#177).
Full changelog: https://github.com/golang-design/clipboard/compare/v0.10.0...v0.11.0
- v0.10.02026-09-25 · 2026-09-25 22:35 UTC
查看更新说明
FreeBSD gets native Wayland, the primary selection works under
ext-data-control, and the docs are rewritten for the people reading them. No API changes:go get golang.design/x/[email protected]is a drop-in upgrade from v0.9.0.New
Native Wayland on FreeBSD (#173, #174). The pure-Go Wayland backend Linux uses now runs on FreeBSD too. Under a compositor that offers data-control, such as sway, Hyprland or KDE Plasma from FreeBSD packages, the clipboard no longer needs XWayland, and without XWayland it now works at all. Nothing to configure: when
WAYLAND_DISPLAYis set and a data-control manager is advertised, Wayland is used; otherwise X11, as before.It is tested in CI: a new job runs the whole test suite as a client of headless sway 1.12 in a FreeBSD VM, against
wl-copy/wl-pastefrom FreeBSD packages. OpenBSD and NetBSD compile the same path, but it is untested there.Fixed
The primary selection under
ext-data-control(#175).FromPrimary()said the middle-click clipboard was unsupported under every compositor offeringext-data-control-v1, such as current sway, KWin and GNOME 49, although that protocol has had it since its first version. The backend was using the wlroots protocol's version rule for both. The new FreeBSD job found this: its sway prefersext, while Ubuntu's older sway offers only the wlroots protocol.Docs
README and package docs rewritten (#176). They now open with a quick start that compiles, followed by a platform table, a feature table, and one short section per task. Examples that no longer compiled against v0.9.0 are fixed, and so are function docs that had gone stale:
Initno longer warns about libx11-dev and panics, andRead,WriteAll,FromPrimaryandErrNoDatanow describe the errors they actually return.Thanks
Thanks to @halcyon for asking for FreeBSD Wayland support in #173.
Full changelog: https://github.com/golang-design/clipboard/compare/v0.9.0...v0.10.0
- v0.9.02026-08-21 · 2026-08-21 08:52 UTC
查看更新说明
The largest release this package has had: a breaking API change that makes failures visible and operations cancellable, four new capabilities, and a browser backend that the API change made possible.
Every open issue on the tracker is closed by this release.
⚠️ Breaking:
context.Contextin,erroroutReadused to returnnilfor every kind of failure, so you could not tell an empty clipboard from a missing X server — the package even carried an internal debug flag whose only job was printing that difference to stderr. And a read could not be bounded: on X11 it might sit for five seconds with no way for you to say otherwise.Every call that moves bytes now takes a context first and returns an error last.
before after b := clipboard.Read(f)b, err := clipboard.Read(ctx, f)ch := clipboard.Write(f, b)ch, err := clipboard.Write(ctx, f, b)fs := clipboard.Formats()fs, err := clipboard.Formats(ctx)v, err := clipboard.ReadAs(f, dec)v, err := clipboard.ReadAs(ctx, f, dec)Init,RegisterandWatchare unchanged at the call site.Watchdid change signature —Watch(ctx, t ...Format)becameWatch(ctx, opts ...Option)— butFormatsatisfiesOption, soclipboard.Watch(ctx, clipboard.FmtText)still compiles exactly as before.context.TODO()is a correct first step, and code that ignored failures can keep doing so with_. When you want the cause, three sentinels tell the cases apart:b, err := clipboard.Read(ctx, clipboard.FmtImage) switch { case errors.Is(err, clipboard.ErrNoData): // nothing to paste case errors.Is(err, clipboard.ErrUnavailable): // no clipboard to reach case errors.Is(err, clipboard.ErrUnsupported): // not possible on this platform }The context is honored as far as each platform allows: every backend checks it before starting, and X11 applies your deadline to the wire read, capped by the package ceiling. Elsewhere the calls are effectively immediate, so the entry check is the whole of it — promising more would be a lie.
This is a pre-1.0 module, so the change arrives as a minor version rather than a new import path. Full migration guide in the README.
New
Publish several formats in one copy — the rich-text behavior every native clipboard has. Calling
Writetwice does not do this: each write replaces the whole clipboard, so only the last format would survive.html := clipboard.Register("text/html") clipboard.WriteAll(ctx, clipboard.Item{Format: html, Bytes: markup}, clipboard.Item{Format: clipboard.FmtText, Bytes: plain}, )Copy and paste files, the way a file manager does —
CF_HDROPon Windows,NSFilenamesPboardTypeon macOS,text/uri-liston X11 and Wayland, all behind one built-in format.clipboard.WriteFiles(ctx, []string{"/home/me/report.pdf"}) paths, err := clipboard.ReadFiles(ctx)The primary (middle-click) selection on X11 and Wayland — a second clipboard this package could not previously see at all.
sel, err := clipboard.Read(ctx, clipboard.FmtText, clipboard.FromPrimary())Limit how many times a write is served, so a secret can leave the clipboard after it is pasted. X11 and Wayland only — see the caveat below.
clipboard.Write(ctx, clipboard.FmtText, password, clipboard.Loops(1))Browser support (js/wasm), text only. Previously
js/wasmreported "cannot use when CGO_ENABLED=0", which was untrue and unhelpful.
Fixed
- Custom MIME types now resolve to the names applications actually use.
Register("image/png")used to register a Windows format literally namedimage/png, which nothing publishes, so the PNG bytes Chromium, Firefox and Office put on the clipboard were unreachable. The same asymmetry on macOS meantFormatscould return a token thatReadthen returned nothing for. - Windows
Watchis event-driven, viaAddClipboardFormatListenerinstead of a one-second pol
- Custom MIME types now resolve to the names applications actually use.
- v0.8.0v0.8.0 — a community milestone2026-06-07 · 2026-06-07 12:09 UTC
查看更新说明
v0.8.0 — a community milestone 🎉
This is by far the largest release in the project's history — and it exists because of you. Every feature below started as a community issue, a prototype, a design discussion, or a bug report. Thank you to everyone who reported, proposed, prototyped, reviewed, and pushed for these — your input directly shaped this release. 🙏
Heads up — one breaking change:
Watchnow returns<-chan Datainstead of<-chan []byte. Migration is one line: readdata.Bytes(and you can now inspectdata.Format).✨ Highlights
- Cgo-free on every desktop platform. macOS (purego/Obj-C), Linux/X11, and the BSDs now talk to the OS clipboard with no C toolchain at build time and no
libX11/libwaylandat runtime (Windows was already Cgo-free). Cross-compiling to desktop "just works." (#69, #25, #55) - Native Wayland support. A pure-Go data-control backend (
ext-data-control-v1/zwlr_data_control_manager_v1), event-drivenWatch, auto-selected over X11 when available, with XWayland fallback. (#6) - Custom, MIME-typed formats.
Register(mime) Format+ReadAs[T]give raw, passthrough read/write/watch for any MIME type — no conversion, no new mandatory dependency, no platform detail leaking into your code. (#17, subsumes #40) - Clipboard enumeration.
Formats() []Formatreports what's on the clipboard right now (auto-registering MIME types it discovers), andFormat.MIME()tells you what a token is. (#89) - Variadic, format-tagged
Watch.Watch(ctx, ...Format) <-chan Datawatches several formats at once and tags each change with its format (no args watches the built-ins). (#89) - Flexible image input.
Write(FmtImage, …)now accepts JPEG/GIF/WebP/… (when you blank-import the decoder) and normalizes to canonical PNG;Read(FmtImage)always returns PNG. (#155)
🐛 Fixes
- Windows: transparent images no longer paste too dark — images are stored/read with straight (non-premultiplied) alpha to match
CF_DIBV5. Verified end-to-end via a real Windows consumer in CI. (#105) - Windows: 24-bit (and other non-32-bit) DIB images now decode instead of returning nil. (#65)
- Windows:
OpenClipboardno longer busy-waits forever — bounded backoff + timeout when another app holds the clipboard. (#144) Watchno longer leaks — tickers are stopped and the send honors context cancellation. (#153)
📦 Dependencies
- Adds the first-party, pure-Go X11 codec
golang.design/x/x11v0.2.0 (extracted from this repo; reusable elsewhere). - iOS/Android continue to use
gomobile(Cgo); mobile keeps text-only support.
🙏 Thanks
This release is the work of many hands. With gratitude to:
- Wayland: @trading-peter (#6), @ajayd-san (#61)
- Dropping Cgo: @TotallyGamerJet (the purego prototype, #83), @gen2brain (#25), @sarumaj (#69), @arturbrzoz (#55), @microo8 (#20)
- Custom formats & raw access: @dmzlingyin, @HuakunShen, @MarvinJWendt (#17), @rams3sh (#40)
- Watch-all & enumeration: @xiebruce (#89)
- Images on Windows / image formats: @allanpk716 (#65), @matwachich (#48), @AlejandroSuero (#58), @jmmemo (#38), @c17abab (#45)
- Bug reports & feature requests that shaped the roadmap: @fanybook (#59), @dongziyudongziyu (#37), @Esword618 (#50), @jinmao88 (#31), @gucio321 (#67), @ValorZard (#64), @qjerome (#22)
…and everyone who joined the discussions, tested pre-release behavior, and filed clear, actionable issues. Thank you all. ❤️
Migration
// Before (v0.7.x): for data := range clipboard.Watch(ctx, clipboard.FmtText) { use(data) // data was []byte } // After (v0.8.0): for data := range clipboard.Watch(ctx, clipboard.FmtText) { use(data.Bytes) // data is clipboard.Data{Format, Bytes} }Full changelog: https://github.com/golang-design/clipboard/compare/v0.7.1...v0.8.0
- Cgo-free on every desktop platform. macOS (purego/Obj-C), Linux/X11, and the BSDs now talk to the OS clipboard with no C toolchain at build time and no
- v0.7.12025-06-14 · 2025-06-14 10:43 UTC
查看更新说明
What's Changed
- Remove unused
constandtypeby @y-yagi in https://github.com/golang-design/clipboard/pull/44 - all: remove old format tag lines by @y-yagi in https://github.com/golang-design/clipboard/pull/46
- Upgrade to Go 1.24 by @changkun in https://github.com/golang-design/clipboard/pull/77
- Handle CGO disabled with error by @changkun in https://github.com/golang-design/clipboard/pull/78
- linux: fix grammar in clipboard_read comment by @changkun in https://github.com/golang-design/clipboard/pull/74
- Fix Linux read error handling by @changkun in https://github.com/golang-design/clipboard/pull/73
- Remove vendor directory by @changkun in https://github.com/golang-design/clipboard/pull/79
- Update golang.org/x dependencies by @changkun in https://github.com/golang-design/clipboard/pull/80
- Add Wayland note by @changkun in https://github.com/golang-design/clipboard/pull/81
- Import golang.org/x/exp/shiny instead of golang.org/x/exp by @tslocum in https://github.com/golang-design/clipboard/pull/82
New Contributors
- @y-yagi made their first contribution in https://github.com/golang-design/clipboard/pull/44
- @tslocum made their first contribution in https://github.com/golang-design/clipboard/pull/82
Full Changelog: https://github.com/golang-design/clipboard/compare/v0.7.0...v0.7.1
- Remove unused
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
clipboard

Copy and paste from Go, the same way on every platform.
import "golang.design/x/clipboard"
- Text, images, files, and any MIME type you register
- macOS, Windows, Linux, FreeBSD, OpenBSD, NetBSD, iOS, Android and the browser
- No Cgo on the desktop: no C compiler to build, no
libX11orlibwaylandto run
Quick start
package main
import (
"context"
"fmt"
"log"
"golang.design/x/clipboard"
)
func main() {
// Call Init once, before anything else. It fails if there is no
// clipboard to talk to, such as on a Linux server with no display.
if err := clipboard.Init(); err != nil {
log.Fatal(err)
}
ctx := context.Background()
// Copy.
if _, err := clipboard.Write(ctx, clipboard.FmtText, []byte("hello, world")); err != nil {
log.Fatal(err)
}
// Paste.
b, err := clipboard.Read(ctx, clipboard.FmtText)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(b)) // hello, world
}
Platforms
| Platform | Talks to | Needs at runtime |
|---|---|---|
| macOS | the system pasteboard | nothing |
| Windows | the Win32 clipboard | nothing |
| Linux | Wayland or X11 | a Wayland compositor with data-control, or an X server |
| FreeBSD | Wayland or X11 | the same as Linux |
| OpenBSD, NetBSD | X11 (Wayland untested) | an X server |
| iOS, Android | the system clipboard, via gomobile | nothing; text only |
| Browser (js/wasm) | navigator.clipboard | https; text only |
On Linux and the BSDs the package picks Wayland by itself when the compositor offers the data-control protocol — GNOME 49 and later, KDE Plasma, Sway, Hyprland and other wlroots compositors — and X11 otherwise, which under an older Wayland compositor means XWayland. Nothing needs configuring.
CI runs the full test suite on macOS, Windows, Linux (X11 and Wayland) and FreeBSD (Wayland), and builds for OpenBSD. NetBSD is best-effort.
What works where
"Desktop" means macOS, Windows, Linux and the BSDs.
| Feature | API | Where |
|---|---|---|
| Text | FmtText | everywhere |
| Images (PNG) | FmtImage | desktop |
| Files | ReadFiles, WriteFiles, FmtFiles | desktop |
| Your own MIME types | Register | desktop |
| Several formats in one copy | WriteAll | desktop |
| List what is on the clipboard | Formats | desktop |
| Watch for changes | Watch | everywhere except the browser |
| The middle-click clipboard | FromPrimary | X11 and Wayland |
| Forget after N pastes | Loops | X11 and Wayland |
| Spot passwords from a password manager | Sensitive, Data.Sensitive | desktop |
Where a feature is missing, the call returns ErrUnsupported or does the
nearest safe thing: WriteAll publishes only your first item, Formats returns
an empty list, and Loops is ignored.
Usage
Text and images
clipboard.Write(ctx, clipboard.FmtText, []byte("some text")) // UTF-8
clipboard.Write(ctx, clipboard.FmtImage, pngBytes) // PNG
text, err := clipboard.Read(ctx, clipboard.FmtText)
img, err := clipboard.Read(ctx, clipboard.FmtImage) // always PNG
Images always come out as PNG, because PNG keeps transparency and every
platform understands it. Write also takes other encodings once you import
their decoder, and converts them to PNG for you:
import _ "image/jpeg" // or _ "golang.org/x/image/webp"
clipboard.Write(ctx, clipboard.FmtImage, jpegBytes) // stored as PNG
To put the bytes on the clipboard unchanged — a JPEG that stays a JPEG — use a custom format instead.
Errors
b, err := clipboard.Read(ctx, clipboard.FmtText)
switch {
case errors.Is(err, clipboard.ErrNoData): // nothing on the clipboard in this format
case errors.Is(err, clipboard.ErrUnavailable): // no clipboard to reach
case errors.Is(err, clipboard.ErrUnsupported): // this platform cannot do that
}
Every call takes a context.Context. It is checked before the call starts, and
on X11 a read also gives up at your deadline.
Know when your copy is replaced
Write returns a channel that fires once, when something else replaces what
you wrote:
changed, err := clipboard.Write(ctx, clipboard.FmtText, []byte("text data"))
if err != nil {
log.Fatal(err)
}
<-changed
fmt.Println(`"text data" is no longer on the clipboard`)
You can ignore the channel. The data is on the clipboard as soon as Write
returns, and the channel never fires if nobody else writes, so do not wait on
it to learn that the write finished.
Watch for changes
for data := range clipboard.Watch(ctx, clipboard.FmtText) {
fmt.Println(string(data.Bytes))
}
Pass several formats, or none to watch text, images and files together. Each value says which format changed:
for data := range clipboard.Watch(ctx) {
switch data.Format {
case clipboard.FmtText:
fmt.Println("text:", string(data.Bytes))
case clipboard.FmtImage:
fmt.Println("image:", len(data.Bytes), "bytes")
}
}
The channel closes when ctx is canceled. Wayland and Windows report changes
as they happen; the other platforms check once a second.
Your own formats
Any MIME type — text/html, image/jpeg, application/pdf — can be used as a
format:
html := clipboard.Register("text/html")
clipboard.Write(ctx, html, []byte("<b>hi</b>"))
b, err := clipboard.Read(ctx, html)
The bytes are moved exactly as given, with no conversion. Register returns
the same value every time for the same MIME type, and you can call it before
Init. To read and decode in one step, use ReadAs:
doc, err := clipboard.ReadAs(ctx, html, parseHTML) // parseHTML: func([]byte) (*Node, error)
On macOS and Windows, common MIME types are translated to the names other apps
use there — image/png becomes public.png on macOS and PNG on Windows — so
browsers, Office and Preview understand them. Any other type is used as it is:
it round-trips through this package, but other apps may not recognize it.
Several formats in one copy
"Copy as rich text" puts the same content on the clipboard in several formats,
and the app you paste into takes the best one it understands. Use WriteAll,
most preferred first:
html := clipboard.Register("text/html")
clipboard.WriteAll(ctx,
clipboard.Item{Format: html, Bytes: []byte("<b>hi</b>")},
clipboard.Item{Format: clipboard.FmtText, Bytes: []byte("hi")},
)
Calling Write twice does not do this: every write replaces the whole
clipboard, so only the last format would be left.
Files
Copy files the way a file manager does, so they paste into Finder, Explorer, Nautilus or Dolphin:
clipboard.WriteFiles(ctx, []string{"/home/me/report.pdf", "/home/me/notes.txt"})
paths, err := clipboard.ReadFiles(ctx)
Paths must be absolute. Only the paths are copied, not the files themselves,
so the files must still exist when someone pastes. For Read, Write, Watch
and WriteAll, the same list is available as the FmtFiles format, whose
bytes are a text/uri-list.
What is on the clipboard?
formats, err := clipboard.Formats(ctx)
for _, f := range formats {
fmt.Println(f.MIME()) // text/plain;charset=utf-8, image/png, text/html, ...
}
Every format it returns can be passed straight to Read. MIME types you have
not registered yet are registered for you.
The middle-click clipboard
X11 and Wayland have a second clipboard, the primary selection: whatever you
last selected with the mouse, pasted with the middle button. Add
FromPrimary() to any call to use it:
sel, err := clipboard.Read(ctx, clipboard.FmtText, clipboard.FromPrimary())
clipboard.Write(ctx, clipboard.FmtText, []byte("hi"), clipboard.FromPrimary())
ch := clipboard.Watch(ctx, clipboard.FmtText, clipboard.FromPrimary())
On Wayland this needs a compositor offering ext-data-control-v1, or version
2 of the wlroots data-control protocol; current ones do. Other platforms have
no second clipboard. There these calls return ErrUnsupported rather than
touching the regular clipboard, which would wipe what the user had copied.
Paste once, then gone
Loops(n) removes what you wrote after it has been pasted n times, which is
useful for passwords:
clipboard.Write(ctx, clipboard.FmtText, password, clipboard.Loops(1))
This works on X11 and Wayland only. Everywhere else it is silently ignored, so it will not clear a secret on Windows or macOS. The reason is how those platforms work: on X11 and Wayland your program hands the data to each app that pastes, so it can count; on Windows and macOS the system keeps the copy, and your program never hears about pastes.
Every delivery counts, including a Read or Watch in your own program, and
an app that asks for two formats in one paste uses up two.
Leave passwords alone
Password managers mark the passwords they copy, so that clipboard managers
and sync tools don't keep them. Sensitive tells you whether the current copy
carries that mark, and every value from Watch says it too:
for data := range clipboard.Watch(ctx, clipboard.FmtText) {
if data.Sensitive {
continue // a password: don't store or upload it
}
save(data.Bytes)
}
It reads the marks password managers actually set: org.nspasteboard.ConcealedType
on macOS, ExcludeClipboardContentFromMonitorProcessing on Windows, and
x-kde-passwordManagerHint on X11 and Wayland. iOS, Android and the browser
have no such mark to read, so there Sensitive returns ErrUnsupported
rather than a false "safe".
Command-line tool
gclip copies and pastes from the shell:
$ go install golang.design/x/clipboard/cmd/gclip@latest
$ gclip
gclip is a command that provides clipboard interaction.
usage: gclip [-copy|-paste] [-f <file>]
options:
-copy
copy data to clipboard
-f string
source or destination to a given file path
-paste
paste data from clipboard
examples:
gclip -paste paste from clipboard and prints the content
gclip -paste -f x.txt paste from clipboard and save as text to x.txt
gclip -paste -f x.png paste from clipboard and save as image to x.png
cat x.txt | gclip -copy copy content from x.txt to clipboard
gclip -copy -f x.txt copy content from x.txt to clipboard
gclip -copy -f x.png copy x.png as image data to clipboard
gclip -copy keeps running until something else replaces what it copied, so
send it to the background when you need the shell back:
$ cat x.txt | gclip -copy &
See cmd/gclip for more, and cmd/gclip-gui for a demo app for iOS and Android.
Platform notes
-
Linux and the BSDs: your program owns what it copies. On X11 and Wayland the program that writes serves the data to every app that pastes. When it exits, the data goes with it, unless a clipboard manager has kept a copy (most keep text; few keep images). Keep your program running for as long as the data should be pasteable. The channel
Writereturns tells you when it is no longer needed. -
Wayland needs data-control. The native backend uses the data-control protocol, which works without a window or keyboard focus. Compositors without it, such as GNOME before 49, are reached through XWayland instead. Under data-control, a program cannot read back its own custom-format writes, though other apps can.
-
No display (servers, CI). Start a virtual X server:
apt install -y xvfb Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & export DISPLAY=:99.0 -
Browser. The page must be served over https (or from localhost while you develop);
Inittells you if it is not. The browser allows a read only after a user action such as a click, and asks the user for permission. CallReadandWritefrom a goroutine that your event handler starts, not in the handler itself, or the handler never returns. Only text is supported. -
Windows services. A service runs in Session 0, which has a clipboard of its own that the logged-in user never sees:
ReadandWritework, but only within the service, andWatchnever sees what the user copies. Windows offers no way around this. Do the clipboard work in a helper process inside the user's session instead, for example one started withCreateProcessAsUserusing the token fromWTSQueryUserToken(WTSGetActiveConsoleSessionId()), and talk to it over IPC. -
File lists. The "cut" flag Explorer uses to mean move is not exposed, so every file list reads as a copy.
-
Testing images. To put a screenshot on the clipboard:
Ctrl+Shift+Cmd+4on macOS,Ctrl+Shift+PrintScreenon Ubuntu,Shift+Win+Son Windows.
Migrating to v0.9.0
v0.9.0 made every call that moves data take a context.Context and return an
error. You can now tell an empty clipboard from one you cannot reach, and put
a deadline on a read. Update calls like this:
| before | after |
|---|---|
b := clipboard.Read(f) | b, err := clipboard.Read(ctx, f) |
ch := clipboard.Write(f, b) | ch, err := clipboard.Write(ctx, f, b) |
ch := clipboard.WriteAll(items...) | ch, err := clipboard.WriteAll(ctx, items...) |
fs := clipboard.Formats() | fs, err := clipboard.Formats(ctx) |
p := clipboard.ReadFiles() | p, err := clipboard.ReadFiles(ctx) |
clipboard.WriteFiles(paths) | clipboard.WriteFiles(ctx, paths) |
clipboard.ReadAs(f, dec) | clipboard.ReadAs(ctx, f, dec) |
Watch already took a context and is unchanged. Passing context.TODO() is a
fine first step, and if you ignored failures before, _ keeps doing that.
Who is using this package?
This package was built for midgard, which syncs the clipboard across machines and can share clipboard content through a public link. For more projects, see the wiki.
License
MIT | © 2021 The golang.design Initiative Authors, written by Changkun Ou.