More work on dnd kitten

This commit is contained in:
Kovid Goyal 2026-04-30 17:18:57 +05:30
parent d70ec000ff
commit bddf6d5bbd
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
3 changed files with 62 additions and 4 deletions

View file

@ -321,7 +321,7 @@ operation, it indicates the drag should be started by sending ``t=P:x=-1``. At
this time if the user has already cancelled the drag or the terminal determines
the drag operation is not allowed, it must respond with ``t=E ; EPERM``. If any
other error occurs starting the drag operation, it must respond with the appropriate
POSIX error code. If it determines that the image data after conversion to
POSIX error name. If it determines that the image data after conversion to
display format is too large, it must respond with ``t=E ; EFBIG``. If the drag
operation is successfully started, it must respond with ``t=E ; OK``.

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 {