gioui.org@v0.6.1-0.20240506124620-7a9ce51988ce/io/input/clipboard.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 package input 4 5 import ( 6 "io" 7 8 "gioui.org/io/clipboard" 9 "gioui.org/io/event" 10 ) 11 12 // clipboardState contains the state for clipboard event routing. 13 type clipboardState struct { 14 receivers []event.Tag 15 } 16 17 type clipboardQueue struct { 18 // request avoid read clipboard every frame while waiting. 19 requested bool 20 mime string 21 text []byte 22 } 23 24 // WriteClipboard returns the most recent data to be copied 25 // to the clipboard, if any. 26 func (q *clipboardQueue) WriteClipboard() (mime string, content []byte, ok bool) { 27 if q.text == nil { 28 return "", nil, false 29 } 30 content = q.text 31 q.text = nil 32 return q.mime, content, true 33 } 34 35 // ClipboardRequested reports if any new handler is waiting 36 // to read the clipboard. 37 func (q *clipboardQueue) ClipboardRequested(state clipboardState) bool { 38 req := len(state.receivers) > 0 && q.requested 39 q.requested = false 40 return req 41 } 42 43 func (q *clipboardQueue) Push(state clipboardState, e event.Event) (clipboardState, []taggedEvent) { 44 var evts []taggedEvent 45 for _, r := range state.receivers { 46 evts = append(evts, taggedEvent{tag: r, event: e}) 47 } 48 state.receivers = nil 49 return state, evts 50 } 51 52 func (q *clipboardQueue) ProcessWriteClipboard(req clipboard.WriteCmd) { 53 defer req.Data.Close() 54 content, err := io.ReadAll(req.Data) 55 if err != nil { 56 return 57 } 58 q.mime = req.Type 59 q.text = content 60 } 61 62 func (q *clipboardQueue) ProcessReadClipboard(state clipboardState, tag event.Tag) clipboardState { 63 for _, k := range state.receivers { 64 if k == tag { 65 return state 66 } 67 } 68 n := len(state.receivers) 69 state.receivers = append(state.receivers[:n:n], tag) 70 q.requested = true 71 return state 72 }