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  }