golang-design / clipboard

📋 cross-platform clipboard package that supports accessing text and image in Go (macOS/Linux/Windows/Android/iOS)

Home Page:https://golang.design/x/clipboard

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

bug: Image Write Doesn't Seem to Work on Linux and Windows (Ubuntu 20.04)

HuakunShen opened this issue · comments

My computer:

  • OS: Ubuntu 20.04, 5.15.0-56-generic
  • Arch: amd64
  • Display manager: X11

Sample 1

If I take a screenshot, and run the following code, I can no longer access the screenshot.

The code below simply reads the image, and write it back after 10 seconds.

func main() {
	err := clipboard.Init()
	checkErr(err)

	imgBuf := clipboard.Read(clipboard.FmtImage)
	fmt.Println(len(imgBuf))
	time.Sleep(10 * time.Second)
	clipboard.Write(clipboard.FmtImage, imgBuf)
}

Sample 2

I tried to use a base64 image string for testing. The code writes the image and read it back then compare with the source.

stdout outputs "true" in the end (on ubuntu), but I can't paste the image out. It seems like the image is written to somewhere not recognized by the OS.

This sample works on MacOS and Windows (Windows outputs false in the end but image can be pasted, seems like there were some transformation applied.)

func main() {
	sampleBase64Img := "iVBORw0KGgoAAAANSUhEUgAAABcAAAAXCAYAAADgKtSgAAAABHNCSVQICAgIfAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAAtdEVYdENyZWF0aW9uIFRpbWUAVHVlIDEzIERlYyAyMDIyIDA0OjM5OjI1IFBNIEVTVH9UhTgAAAIhSURBVEiJrZQxaBNhFMd/d7leYprGWEMkldIONta4xFAHqWiEYMHBpRktCkWHUoJOcexsF8EO6iA4KE4O0jgIgk6iUrDadrKobW3TJhgSm6S5kPscUhQbcvkS+qbHvXe/7//e979TwuGwYE8c6Du691HDmJqI/80TicR/NVWa0kZYwAV9wW1OHqobbH/gJ6Ip7t/5xqPrWcKe1g+xXIsQgK1K4EyGu1PrXB0wUfYHrvLqQT+Tjw+yVADFXWQ8vsGoX34Ca+WGxvxbH/FpL58KoHYWuXElR4+kfCm37Kx4mE46MAQ4j+e43C+nXh2PTBILRQm4dIs2hbX3bj5XAbXCULAipUr9svULvXuI8+FLHLM3ntfM63zPAQj8vgo2GfiHpWe8XF5H6AMM+lyN3SAUSkatatcl1wIm+XyKklBw6M6WrNYUrmsOHA4nuiLYKRdp/3usD+1a5GYtEwVyRWt4q1Nps3NPd1OD3/lq407VpNNRO7psyP3vtPXsilSjerhMwA2g8HNTw0LGv3d0zzAjp8cY6fdb2EsQPJdnUAXMDj4udGDKwGOnztKr51hOpRqoEXhDaW5HDWwKbC96eLEqt31tczXJ/I9FMpX6q+zqKXDxQpaxSAmvDcx8JzNP3GxKWkp7/XWhQclkOLbBrVCNVMm4uDdzhNktec9ozRrMos67N908THaxXJLmNoMrzD3vZXTLTtpoDSoFT6/Z26Puxh8ZKK5kzvJifAAAAABJRU5ErkJggg=="
	sampleImgBuf, _ := base64.StdEncoding.DecodeString(sampleBase64Img)
	clipboard.Write(clipboard.FmtImage, sampleImgBuf)
	time.Sleep(time.Second)
	imgRead := clipboard.Read(clipboard.FmtImage)
	decodedImgRead := base64.StdEncoding.EncodeToString(imgRead)
	fmt.Println(decodedImgRead == sampleBase64Img)
}

It seems like doing this makes image writing works on Linux Ubuntu, even without triggering changed. Why does this happen?

And this will block the program.

changed := clipboard.Write(clipboard.FmtImage, sampleImgBuf)
select {
case <-changed:
    println(`Image Updated`)
}

On Linux, you must keep the application running so that others can read your data. See #15 for another discussion. Closing because this is not a bug, and feel free to reopen the issue if this is actually a bug.

@changkun Thanks, I kind of noticed that the program has to be running. I did a work-around with xclip.
Is it the same on Windows? I also can't write image on Windows.

That's not a requirement on Windows. Is the problem reproducible on latest release?

@changkun Yes I tried to write an image on Windows on the latest release and it doesn't work.

Here is my sample code.

package main

import (
	"encoding/base64"
	"golang.design/x/clipboard"
	"log"
)

func main() {
	if err := clipboard.Init(); err != nil {
		log.Fatal(err)
	}
	base64Str := "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAgACADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDumIVSx6AZrD0LxPba9d3sFujD7K+xie5rVvpPJsJ5P7qE/pXn3woXdY6rfdWluWNcEYpxbOlvVI9JormvDPioa/eahbGHy3tJNh966WpaadmUnfYy/ESzP4fvVgUtK0TBQOpOK8s8Kaj4q8P6MbC38PPJlifMbjOa9npMD0FXGdlaxLjd3ueFeDr/AMTReJtRjsrSPzpJd1yr/wAHPavc4S5hQyDD4G761mWXh6xsNWudSgQrPcffPY1rUVJqT0CEWkf/2Q=="
	imgBuf, err := base64.StdEncoding.DecodeString(base64Str)
	if err != nil {
		log.Fatal(err)
	}
	clipboard.Write(clipboard.FmtImage, imgBuf)
}

And if I use select to monitor changed, there is a deadlock.

changed := clipboard.Write(clipboard.FmtImage, imgBuf)
select {
case <-changed:
    println(`"text data" is no longer available from clipboard.`)
}
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive (nil chan)]:
main.main()
	C:/Users/username/Desktop/clipboard-app/main.go:20 +0xce

Is your image png encoded?

@changkun Yes, if you copy the base64 string to https://onlinepngtools.com/convert-base64-to-png
The image can be rendered.

Wait, it seems like it's not png encoded even if it can be displayed.
I tried to take a screenshot and read it to string with go clipboard, then write it back. It works!

So does this mean other type of image encoding are not supported?
I will experiment a few more things, thanks!

As documented in the API, the image buffer must be png encoded: https://pkg.go.dev/golang.design/x/clipboard#Write

It is recommended that you encode it using image/png package to encode the bytes buffer

There are underlying implementation reasons, but it is not important for users who are not interested in the details.