More work on DnD kitten

This commit is contained in:
Kovid Goyal 2026-04-21 08:19:22 +05:30
parent 01e453a048
commit 9a011dea3e
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
3 changed files with 46 additions and 5 deletions

View file

@ -323,10 +323,11 @@ func run_loop(opts *Options, drop_dests map[string]*drop_dest, drag_sources map[
if drop_status.remote_phase_started {
return on_remote_drop_data(cmd)
}
if cmd.X < 0 || cmd.X > len(drop_status.accepted_mimes) {
idx := cmd.X - 1
if idx < 0 || idx > len(drop_status.accepted_mimes) {
return fmt.Errorf("terminal sent drop data for a index outside the list of accepted MIMEs")
}
mime := drop_status.accepted_mimes[cmd.X]
mime := drop_status.accepted_mimes[idx]
dest := drop_dests[mime]
if cmd.Xp == 1 && mime == "text/uri-list" {
drop_status.is_remote_client = true
@ -428,6 +429,8 @@ func run_loop(opts *Options, drop_dests map[string]*drop_dest, drag_sources map[
} else {
send_test_response("")
}
case "DROP_IS_REMOTE":
send_test_response(utils.IfElse(drop_status.is_remote_client, "True", "False"))
default:
send_test_response("UNKNOWN TEST COMMAND: " + string(cmd.Payload))
}

View file

@ -2093,15 +2093,15 @@ dnd_test_fake_drop_data(PyObject *self UNUSED, PyObject *args) {
unsigned long long window_id;
const char *mime;
RAII_PY_BUFFER(data);
int error_code = 0;
if (!PyArg_ParseTuple(args, "Ksy*|i", &window_id, &mime, &data, &error_code)) return NULL;
int error_code = 0, no_eod = 0;
if (!PyArg_ParseTuple(args, "Ksy*|ii", &window_id, &mime, &data, &error_code, &no_eod)) return NULL;
Window *w = window_for_window_id((id_type)window_id);
if (!w) { PyErr_SetString(PyExc_ValueError, "Window not found"); return NULL; }
if (error_code > 0) {
drop_dispatch_data(w, mime, NULL, -(ssize_t)error_code);
} else if (data.len > 0) {
drop_dispatch_data(w, mime, (const char*)data.buf, (ssize_t)data.len);
drop_dispatch_data(w, mime, NULL, 0); // mandatory end-of-data signal
if (!no_eod) drop_dispatch_data(w, mime, NULL, 0); // mandatory end-of-data signal
} else {
// Empty data: just the end-of-data signal (sz=0 is the sentinel for "no more data").
drop_dispatch_data(w, mime, NULL, 0);
@ -2216,6 +2216,9 @@ dnd_test_probe_state(PyObject *self UNUSED, PyObject *args) {
}
return ans;
}
if (strcmp(q, "drop_getting_data_for_mime") == 0) {
return PyUnicode_FromString(w->drop.getting_data_for_mime ? w->drop.getting_data_for_mime : "");
}
Py_RETURN_NONE;
}

View file

@ -2,8 +2,10 @@
# License: GPLv3 Copyright: 2026, Kovid Goyal <kovid at kovidgoyal.net>
import os
import random
import tempfile
from base64 import standard_b64encode
from functools import partial
from kitty.constants import kitten_exe
from kitty.fast_data_types import (
@ -13,9 +15,11 @@
dnd_set_test_write_func,
dnd_test_cleanup_fake_window,
dnd_test_create_fake_window,
dnd_test_fake_drop_data,
dnd_test_fake_drop_event,
dnd_test_probe_state,
)
from kitty.utils import as_file_url
from . import PTY, BaseTest
from .dnd import WriteCapture
@ -27,6 +31,27 @@ def __call__(self, window_id: int, data: bytes) -> None:
self.pty.write_to_child(data)
def create_fs(base):
join = partial(os.path.join, base)
def w(sz, *path):
if sz == 0:
sz = random.randint(5713, 9879)
with open(join(*path), 'wb') as f:
f.write(os.urandom(sz))
os.makedirs(join('d1', 'sd', 'ssd'))
os.mkdir(join('d2'))
os.symlink('/does-not-exist', join('s1'))
os.symlink('d1', join('sd'))
os.symlink('/', join('sr'))
os.symlink('../d1', join('d1', 'sr'))
w(4096 * 3 + 113, 'some-image.png')
w(0, 'd1', 'f1')
w(0, 'd1', 'f2')
w(0, 'd1', 'sd', 'f1')
w(0, 'd1', 'sd', 'ssd', 'f1')
os.symlink('../moose', join('d1', 'sd', 'ssd', 's1'))
class TestDnDKitten(BaseTest):
def setUp(self):
@ -164,3 +189,13 @@ def dnd_kitten_drop(self, remote_client):
self.send_dnd_command_to_kitten('DROP_MIMES')
self.wait_for_responses(all_mimes)
self.wait_for_state('drop_data_requests', ((1,0,0), (2,0,0)))
self.assertEqual('text/uri-list', self.probe_state('drop_getting_data_for_mime'))
create_fs(self.src_data_dir)
uri_list = []
for x in os.listdir(self.src_data_dir):
uri_list.append(as_file_url(self.src_data_dir, x))
uri_list = ['moose://cow', 'frog:march'] + uri_list
uri_list.insert(3, 'ignore://me')
dnd_test_fake_drop_data(self.capture.window_id, 'text/uri-list', '\r\n'.join(uri_list).encode())
self.send_dnd_command_to_kitten('DROP_IS_REMOTE')
self.wait_for_responses(str(remote_client))