Loop API for DnD transmission

This commit is contained in:
Kovid Goyal
2026-04-16 20:06:12 +05:30
parent b16d199c54
commit 5ea424abeb

View File

@@ -3,6 +3,8 @@
package loop
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt"
@@ -13,8 +15,10 @@ import (
"golang.org/x/sys/unix"
"github.com/kovidgoyal/go-parallel"
"github.com/kovidgoyal/kitty"
"github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/machine_id"
"github.com/kovidgoyal/kitty/tools/utils/style"
"github.com/kovidgoyal/kitty/tools/wcswidth"
)
@@ -653,3 +657,58 @@ func (self *Loop) DrawSizedText(text string, spec SizedText) {
b.WriteString("\a")
self.QueueWriteString(b.String())
}
func (self *Loop) QueueDnDData(metadata map[string]string, payload string, as_base64 bool) IdType {
b := strings.Builder{}
b.Grow(64)
fmt.Fprintf(&b, "\x1b]%d;", kitty.DndCode)
is_first := false
for key, val := range metadata {
if !is_first {
b.WriteString(":")
}
is_first = false
fmt.Fprintf(&b, "%s=%s", key, val)
}
payload_sz := len(payload)
if payload_sz == 0 {
b.WriteString("\x1b\\")
return self.QueueWriteString(b.String())
}
if as_base64 {
payload_sz = base64.RawStdEncoding.EncodedLen(payload_sz)
dest := make([]byte, base64.RawStdEncoding.EncodedLen(len(payload)))
base64.RawStdEncoding.Encode(dest, utils.UnsafeStringToBytes(payload))
payload = utils.UnsafeBytesToString(dest)
}
const chunk_size = 4096
var ans IdType
for i := 0; i < len(payload); i += chunk_size {
end := i + chunk_size
is_last := end >= len(payload)
end = min(end, len(payload))
if i == 0 {
fmt.Fprintf(&b, "m=%d;", utils.IfElse(is_last, 0, 1))
self.QueueWriteString(b.String())
} else {
self.QueueWriteString(fmt.Sprintf("\x1b]%d;m=%d;", kitty.DndCode, utils.IfElse(is_last, 0, 1)))
}
self.QueueWriteString(payload[i:end])
ans = self.QueueWriteString("\x1b\\")
}
return ans
}
func (self *Loop) StartAcceptingDrops(mime_types ...string) {
self.QueueDnDData(map[string]string{"t": "a"}, strings.Join(mime_types, " "), false)
if ans, err := machine_id.MachineId(); err == nil {
mac := hmac.New(sha256.New, []byte("tty-dnd-protocol-machine-id"))
mac.Write(utils.UnsafeStringToBytes(ans))
ans = "1:" + hex.EncodeToString(mac.Sum(nil))
self.QueueDnDData(map[string]string{"t": "a", "x": "1"}, ans, false)
}
}
func (self *Loop) StopAcceptingDrops() {
self.QueueDnDData(map[string]string{"t": "A"}, "", false)
}