mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 14:18:26 +02:00
More work on dnd kitten
This commit is contained in:
@@ -391,7 +391,7 @@ examine the :ref:`machine_id` sent with the enable drag offers
|
||||
from the URI list. To request data for a particular entry, terminals send an
|
||||
escape code of the form::
|
||||
|
||||
OSC _dnd_code ; t=k:x=idx ; base64 encoded file data ST
|
||||
OSC _dnd_code ; t=k:x=idx ST
|
||||
|
||||
Here ``idx`` is the one based index into the list of entries in the
|
||||
``text/uri-list`` MIME type. Then the client can respond with the data
|
||||
|
||||
@@ -23,7 +23,6 @@ var _ = fmt.Print
|
||||
|
||||
type data_request struct {
|
||||
drag_source *drag_source
|
||||
send_remote_data bool
|
||||
index int
|
||||
write_id loop.IdType
|
||||
base64 streaming_base64.StreamingBase64Encoder
|
||||
@@ -51,7 +50,7 @@ type drag_status struct {
|
||||
current_remote_file *remote_data_item
|
||||
dir_handle_counter int
|
||||
remote_item_write_id loop.IdType
|
||||
remote_data_was_sent bool
|
||||
remote_data_requests []int
|
||||
}
|
||||
|
||||
func find_drag_image(drag_sources map[string]*drag_source) image.Image {
|
||||
@@ -66,12 +65,10 @@ func find_drag_image(drag_sources map[string]*drag_source) image.Image {
|
||||
}
|
||||
}
|
||||
var uri_list []string
|
||||
if ds := drag_sources["text/uri-list"]; ds != nil && len(ds.data) > 0 {
|
||||
if q, err := parse_uri_list(string(ds.data)); err == nil {
|
||||
for _, path := range q {
|
||||
if path != "" {
|
||||
uri_list = append(uri_list, path)
|
||||
}
|
||||
if ds := drag_sources["text/uri-list"]; ds != nil {
|
||||
for _, e := range ds.uri_list {
|
||||
if e.path != "" {
|
||||
uri_list = append(uri_list, e.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,16 +99,14 @@ func (dnd *dnd) set_drag_image_text() (err error) {
|
||||
}
|
||||
}
|
||||
if icon == "" {
|
||||
if ds := dnd.drag_sources["text/uri-list"]; ds != nil && len(ds.data) > 0 {
|
||||
if q, err := parse_uri_list(string(ds.data)); err == nil {
|
||||
for _, path := range q {
|
||||
if path != "" && from_path(path) {
|
||||
if ds := dnd.drag_sources["text/uri-list"]; ds != nil {
|
||||
for _, e := range ds.uri_list {
|
||||
if e.path != "" && from_path(e.path) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if icon == "" {
|
||||
icon = strings.TrimSpace(" ")
|
||||
}
|
||||
@@ -219,7 +214,7 @@ func (dnd *dnd) reset_drag() {
|
||||
dnd.drag_status = drag_status{}
|
||||
}
|
||||
|
||||
func (dnd *dnd) on_drag_event(x, y, operation, Y int) (err error) {
|
||||
func (dnd *dnd) on_drag_event(x, y, operation int) (err error) {
|
||||
switch x {
|
||||
case 1:
|
||||
dnd.drag_status.accepted_mime = y
|
||||
@@ -230,14 +225,14 @@ func (dnd *dnd) on_drag_event(x, y, operation, Y int) (err error) {
|
||||
case 4:
|
||||
was_dropped := dnd.drag_status.dropped
|
||||
was_move := dnd.drag_status.accepted_operation == 2
|
||||
was_remote := dnd.drag_status.remote_data_was_sent
|
||||
dnd.reset_drag()
|
||||
if was_dropped && dnd.has_exit_on("drag-finish") {
|
||||
dnd.lp.Quit(0)
|
||||
}
|
||||
if was_dropped && was_move && was_remote {
|
||||
if was_dropped && was_move {
|
||||
if ds := dnd.drag_sources["text/uri-list"]; ds != nil {
|
||||
for _, item := range ds.uri_list {
|
||||
if item.was_sent {
|
||||
if item.metadata.IsDir() {
|
||||
err = os.RemoveAll(item.path)
|
||||
} else {
|
||||
@@ -248,6 +243,7 @@ func (dnd *dnd) on_drag_event(x, y, operation, Y int) (err error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dnd.drag_sources = nil
|
||||
dnd.allow_drags = false
|
||||
dnd.lp.StopOfferingDrags()
|
||||
@@ -256,7 +252,7 @@ func (dnd *dnd) on_drag_event(x, y, operation, Y int) (err error) {
|
||||
}
|
||||
}
|
||||
case 5:
|
||||
if err = dnd.handle_data_request(y, Y == 1); err != nil {
|
||||
if err = dnd.handle_data_request(y); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -272,28 +268,24 @@ func (dnd *dnd) finish_drag(errname string) {
|
||||
dnd.reset_drag()
|
||||
}
|
||||
|
||||
func (dnd *dnd) handle_data_request(idx int, send_remote_data bool) (err error) {
|
||||
func (dnd *dnd) handle_data_request(idx int) (err error) {
|
||||
if idx < 0 || idx >= len(dnd.drag_status.offered_mimes) {
|
||||
dnd.finish_drag("EINVAL")
|
||||
return fmt.Errorf("terminal asked for drag data from MIME list with out of bounds index: %d", idx)
|
||||
}
|
||||
mime := dnd.drag_status.offered_mimes[idx]
|
||||
ds := dnd.drag_sources[mime]
|
||||
send_remote_data = send_remote_data && mime == "text/uri-list" && len(ds.uri_list) > 0
|
||||
for _, dr := range dnd.drag_status.data_requests {
|
||||
if dr.index == idx {
|
||||
dnd.finish_drag("EINVAL")
|
||||
return fmt.Errorf("terminal sent a duplicate drag data request")
|
||||
}
|
||||
}
|
||||
dr := &data_request{drag_source: ds, send_remote_data: send_remote_data, index: idx}
|
||||
dr := &data_request{drag_source: ds, index: idx}
|
||||
if ds.path == "" {
|
||||
dnd.lp.QueueDnDData(DC{Type: 'e', Y: idx, Payload: utils.UnsafeStringToBytes(base64.RawStdEncoding.EncodeToString(ds.data))})
|
||||
dnd.lp.QueueDnDData(DC{Type: 'e', Y: idx}) // EOF
|
||||
if !dr.send_remote_data {
|
||||
return
|
||||
}
|
||||
return dnd.start_remote_data_send(ds)
|
||||
} else {
|
||||
if ds.file != nil {
|
||||
ds.file.Close()
|
||||
@@ -356,9 +348,7 @@ func (dnd *dnd) on_data_request_finished(i int) (err error) {
|
||||
dr.drag_source.file = nil
|
||||
}
|
||||
dnd.drag_status.data_requests = slices.Delete(dnd.drag_status.data_requests, i, i+1)
|
||||
if dr.send_remote_data {
|
||||
err = dnd.start_remote_data_send(dr.drag_source)
|
||||
} else if len(dnd.drag_status.data_requests) > 0 {
|
||||
if len(dnd.drag_status.data_requests) > 0 {
|
||||
err = dnd.send_data_for_data_request(0)
|
||||
}
|
||||
return
|
||||
@@ -386,6 +376,9 @@ func (dnd *dnd) send_remote_dir(path string, idx_in_uri_list, parent_dir_handle,
|
||||
dnd.finish_drag("EIO")
|
||||
return nil, err
|
||||
}
|
||||
for dnd.drag_status.dir_handle_counter < 2 {
|
||||
dnd.drag_status.dir_handle_counter++
|
||||
}
|
||||
handle := dnd.drag_status.dir_handle_counter
|
||||
dnd.drag_status.dir_handle_counter++
|
||||
names := make([]string, 0, len(entries))
|
||||
@@ -447,7 +440,11 @@ func (dnd *dnd) send_next_file_chunk() (err error) {
|
||||
|
||||
func (dnd *dnd) next_remote_item() (err error) {
|
||||
if len(dnd.drag_status.remote_items) < 1 {
|
||||
dnd.lp.QueueDnDData(DC{Type: 'k'}) // inform terminal remote data is finished
|
||||
// current remote data request finished
|
||||
dnd.drag_status.remote_data_requests = dnd.drag_status.remote_data_requests[1:]
|
||||
if len(dnd.drag_status.remote_data_requests) > 0 {
|
||||
return dnd.send_next_remote_data_request()
|
||||
}
|
||||
if len(dnd.drag_status.data_requests) > 0 {
|
||||
err = dnd.send_data_for_data_request(0)
|
||||
}
|
||||
@@ -478,12 +475,31 @@ func (dnd *dnd) next_remote_item() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (dnd *dnd) start_remote_data_send(ds *drag_source) (err error) {
|
||||
dnd.drag_status.dir_handle_counter = 2
|
||||
dnd.drag_status.remote_item_write_id = 0
|
||||
dnd.drag_status.remote_data_was_sent = true
|
||||
func (dnd *dnd) on_drag_remote_data_request(idx int) (err error) {
|
||||
ds := dnd.drag_sources["text/uri_list"]
|
||||
if ds == nil || len(ds.uri_list) < 1 {
|
||||
dnd.finish_drag("EINVAL")
|
||||
return fmt.Errorf("terminal asked for drag data from URI list but no list present")
|
||||
}
|
||||
if idx < 0 || idx >= len(ds.uri_list) {
|
||||
dnd.finish_drag("EINVAL")
|
||||
return fmt.Errorf("terminal asked for drag data from URI list with out of bounds index: %d", idx)
|
||||
}
|
||||
ds.uri_list[idx].was_sent = true
|
||||
dnd.drag_status.remote_data_requests = append(dnd.drag_status.remote_data_requests, idx)
|
||||
if len(dnd.drag_status.remote_data_requests) == 1 {
|
||||
err = dnd.send_next_remote_data_request()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (dnd *dnd) send_next_remote_data_request() (err error) {
|
||||
if len(dnd.drag_status.remote_data_requests) == 0 {
|
||||
return nil
|
||||
}
|
||||
i := dnd.drag_status.remote_data_requests[0]
|
||||
x := dnd.drag_sources["text/uri-list"].uri_list[i]
|
||||
items := []*remote_data_item{}
|
||||
for i, x := range ds.uri_list {
|
||||
if x.metadata.IsDir() {
|
||||
if children, err := dnd.send_remote_dir(x.path, i, 0, i); err != nil {
|
||||
return err
|
||||
@@ -498,7 +514,6 @@ func (dnd *dnd) start_remote_data_send(ds *drag_source) (err error) {
|
||||
f := remote_data_item{idx_in_parent: i, idx_in_uri_list: i, metadata: x.metadata, path: x.path}
|
||||
dnd.drag_status.remote_items = append(dnd.drag_status.remote_items, &f)
|
||||
}
|
||||
}
|
||||
dnd.drag_status.remote_items = append(dnd.drag_status.remote_items, items...)
|
||||
if dnd.drag_status.remote_item_write_id == 0 {
|
||||
return dnd.next_remote_item()
|
||||
|
||||
@@ -31,6 +31,7 @@ type uri_list_item struct {
|
||||
path, uri, human_name string
|
||||
file *os.File
|
||||
metadata os.FileInfo
|
||||
was_sent bool
|
||||
}
|
||||
|
||||
type drag_source struct {
|
||||
@@ -105,7 +106,7 @@ func (dnd *dnd) send_test_response(payload string) {
|
||||
}
|
||||
|
||||
func (dnd *dnd) has_exit_on(event string) bool {
|
||||
for _, e := range strings.Split(dnd.opts.ExitOn, ",") {
|
||||
for e := range strings.SplitSeq(dnd.opts.ExitOn, ",") {
|
||||
if strings.TrimSpace(e) == event {
|
||||
return true
|
||||
}
|
||||
@@ -276,7 +277,9 @@ func (dnd *dnd) run_loop() (err error) {
|
||||
case 'E':
|
||||
return dnd.on_drag_error(cmd)
|
||||
case 'e':
|
||||
return dnd.on_drag_event(cmd.X, cmd.Y, cmd.Operation, cmd.Yp)
|
||||
return dnd.on_drag_event(cmd.X, cmd.Y, cmd.Operation)
|
||||
case 'k':
|
||||
return dnd.on_drag_remote_data_request(cmd.X - 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -426,7 +426,7 @@ class PTY:
|
||||
if isinstance(data, str):
|
||||
data = data.encode('utf-8')
|
||||
if self.log_data_flow:
|
||||
print('t -> c:', data)
|
||||
print('t -> c:', bytes(data))
|
||||
self.write_buf += data
|
||||
if flush:
|
||||
self.process_input_from_child(0)
|
||||
|
||||
Reference in New Issue
Block a user