// Example copy shows how to place text data in the CLIPBOARD selection. package main import "os" import "io" import "log" import "bytes" import "github.com/jezek/xgbutil" import "github.com/jezek/xgb/xproto" import "git.tebibyte.media/tomo/xgbsel" import "github.com/jezek/xgbutil/xprop" import "github.com/jezek/xgbutil/xevent" import "github.com/jezek/xgbutil/xwindow" // data is a very basic implementation of xgbsel.Data that only serves data of // one type. type data struct { buffer io.ReadSeekCloser mime string } func (this *data) Convert (target xgbsel.Target) (io.ReadSeekCloser, bool) { if mime, _ := target.ToMime(); mime == this.mime { return this.buffer, true } else { return nil, false } } func (this *data) Supported () []xgbsel.Target { return xgbsel.MimeToTargets(this.mime) } // nopSeekCloser is like io.NopCloser but for an io.ReadSeeker. type nopSeekCloser struct { io.ReadSeeker } func (nopSeekCloser) Close () error { return nil } func main () { // get data from user log.Println("enter data, ^D when done: ") buffer, _ := io.ReadAll(os.Stdin) data := &data { buffer: nopSeekCloser { ReadSeeker: bytes.NewReader(buffer), }, mime: "text/plain", } // establish connection X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // create window window, err := xwindow.Generate(X) if err != nil { log.Fatalln("could not generate a new window X id:", err) } window.Create(X.RootWin(), 0, 0, 500, 500, xproto.CwBackPixel, 0xffffffff) // obtain claim on CLIPBOARD log.Println("obtaining claim") clipboard, _ := xprop.Atm(X, "CLIPBOARD") claim := xgbsel.NewClaim(window, clipboard, data) // listen for events window.Listen(xproto.EventMaskPropertyChange) xevent.SelectionRequestFun(claim.HandleSelectionRequest).Connect(X, window.Id) log.Println("running main event loop") xevent.Main(X) }