aboutsummaryrefslogtreecommitdiff
path: root/vendor/gioui.org/io/transfer/transfer.go
blob: 85ab68c38ebd9205b516d2f4faefc0b1deb3b0c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Package transfer contains operations and events for brokering data transfers.
//
// The transfer protocol is as follows:
//
//  - Data sources are registered with SourceOps, data targets with TargetOps.
//  - A data source receives a RequestEvent when a transfer is initiated.
//    It must respond with an OfferOp.
//  - The target receives a DataEvent when transferring to it. It must close
//    the event data after use.
//
// When a user initiates a pointer-guided drag and drop transfer, the
// source as well as all potential targets receive an InitiateEvent.
// Potential targets are targets with at least one MIME type in common
// with the source. When a drag gesture completes, a CancelEvent is sent
// to the source and all potential targets.
//
// Note that the RequestEvent is sent to the source upon drop.
package transfer

import (
	"io"

	"gioui.org/internal/ops"
	"gioui.org/io/event"
	"gioui.org/op"
)

// SourceOp registers a tag as a data source for a MIME type.
// Use multiple SourceOps if a tag supports multiple types.
type SourceOp struct {
	Tag event.Tag
	// Type is the MIME type supported by this source.
	Type string
}

// TargetOp registers a tag as a data target.
// Use multiple TargetOps if a tag supports multiple types.
type TargetOp struct {
	Tag event.Tag
	// Type is the MIME type accepted by this target.
	Type string
}

// OfferOp is used by data sources as a response to a RequestEvent.
type OfferOp struct {
	Tag event.Tag
	// Type is the MIME type of Data.
	// It must be the Type from the corresponding RequestEvent.
	Type string
	// Data contains the offered data. It is closed when the
	// transfer is complete or cancelled.
	// Data must be kept valid until closed, and it may be used from
	// a goroutine separate from the one processing the frame..
	Data io.ReadCloser
}

func (op SourceOp) Add(o *op.Ops) {
	data := ops.Write2(&o.Internal, ops.TypeSourceLen, op.Tag, op.Type)
	data[0] = byte(ops.TypeSource)
}

func (op TargetOp) Add(o *op.Ops) {
	data := ops.Write2(&o.Internal, ops.TypeTargetLen, op.Tag, op.Type)
	data[0] = byte(ops.TypeTarget)
}

// Add the offer to the list of operations.
// It panics if the Data field is not set.
func (op OfferOp) Add(o *op.Ops) {
	if op.Data == nil {
		panic("invalid nil data in OfferOp")
	}
	data := ops.Write3(&o.Internal, ops.TypeOfferLen, op.Tag, op.Type, op.Data)
	data[0] = byte(ops.TypeOffer)
}

// RequestEvent requests data from a data source. The source must
// respond with an OfferOp.
type RequestEvent struct {
	// Type is the first matched type between the source and the target.
	Type string
}

func (RequestEvent) ImplementsEvent() {}

// InitiateEvent is sent to a data source when a drag-and-drop
// transfer gesture is initiated.
//
// Potential data targets also receive the event.
type InitiateEvent struct{}

func (InitiateEvent) ImplementsEvent() {}

// CancelEvent is sent to data sources and targets to cancel the
// effects of an InitiateEvent.
type CancelEvent struct{}

func (CancelEvent) ImplementsEvent() {}

// DataEvent is sent to the target receiving the transfer.
type DataEvent struct {
	// Type is the MIME type of Data.
	Type string
	// Open returns the transfer data. It is only valid to call Open in the frame
	// the DataEvent is received. The caller must close the return value after use.
	Open func() io.ReadCloser
}

func (DataEvent) ImplementsEvent() {}