More work on dnd kitten

This commit is contained in:
Kovid Goyal
2026-04-30 17:18:57 +05:30
parent d70ec000ff
commit bddf6d5bbd
3 changed files with 62 additions and 4 deletions

View File

@@ -2,10 +2,57 @@ package dnd
import (
"fmt"
"maps"
"slices"
"strings"
"github.com/kovidgoyal/kitty/tools/utils"
)
var _ = fmt.Print
type drag_status struct {
active bool
active bool
terminal_accepted_drag bool
}
func (dnd *dnd) on_potential_drag_start(cell_x, cell_y int) (err error) {
if !dnd.allow_drags || dnd.drag_status.active {
return
}
mimes := slices.Collect(maps.Keys(dnd.drag_sources))
actions := 3
if dnd.copy_button_region.has(cell_x, cell_y) {
actions = 1
} else if dnd.move_button_region.has(cell_x, cell_y) {
actions = 2
}
dnd.lp.QueueDnDData(DC{Type: 'o', Operation: actions, Payload: utils.UnsafeStringToBytes(strings.Join(mimes, " "))})
total_preloaded_data_sz := 0
for i, mt := range mimes {
s := dnd.drag_sources[mt]
if len(s.data) > 0 && len(s.data)+total_preloaded_data_sz < 64*1024*1024 {
total_preloaded_data_sz += len(s.data)
dnd.lp.QueueDnDData(DC{Type: 'p', X: i, Operation: actions, Payload: utils.UnsafeStringToBytes(strings.Join(mimes, " "))})
}
}
// TODO: set the drag image
dnd.lp.QueueDnDData(DC{Type: 'P', X: -1}) // start drag
dnd.drag_status.active = true
return dnd.render_screen()
}
func (dnd *dnd) on_drag_error(cmd DC) (err error) {
payload := string(cmd.Payload)
switch payload {
case "OK":
if dnd.drag_status.active && !dnd.drag_status.terminal_accepted_drag {
dnd.drag_status.terminal_accepted_drag = true
err = dnd.render_screen()
}
default:
err = fmt.Errorf("terminal responded with drag source error: %s", payload)
}
return
}

View File

@@ -240,6 +240,12 @@ func (dnd *dnd) run_loop() (err error) {
return fmt.Errorf("error from the terminal while reading dropped data: %s", string(cmd.Payload))
case 'r':
return dnd.on_drop_data(cmd)
// Drag source
case 'o':
return dnd.on_potential_drag_start(cmd.X, cmd.Y)
case 'E':
return dnd.on_drag_error(cmd)
}
return nil
}
@@ -305,8 +311,13 @@ func dnd_main(cmd *cli.Command, opts *Options, args []string) (rc int, err error
}
s := drag_source{human_name: src, mime_type: mime}
if src == "-" || src == "/dev/stdin" {
s.human_name = "STDIN"
s.file = os.Stdin
data, err := io.ReadAll(os.Stdin)
if err != nil {
return 1, err
}
if len(data) > 0 {
drag_sources["text/plain"] = drag_source{human_name: "STDIN", mime_type: "text/plain", data: data}
}
} else {
path, err := filepath.Abs(src)
if err != nil {