mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-05-13 08:26:56 +00:00
More work on the dnd kitten
This commit is contained in:
parent
614a32c790
commit
197115cb95
8 changed files with 77 additions and 14 deletions
|
|
@ -33,7 +33,8 @@ func (dnd *dnd) on_potential_drag_start(cell_x, cell_y int) (err error) {
|
|||
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, " "))})
|
||||
dnd.lp.QueueDnDData(DC{Type: 'p', X: i, Operation: actions, Payload: s.data})
|
||||
dnd.lp.QueueDnDData(DC{Type: 'p', X: i, Operation: actions})
|
||||
}
|
||||
}
|
||||
// TODO: set the drag image
|
||||
|
|
@ -56,3 +57,16 @@ func (dnd *dnd) on_drag_error(cmd DC) (err error) {
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (dnd *dnd) reset_drag() {
|
||||
dnd.drag_status = drag_status{}
|
||||
}
|
||||
|
||||
func (dnd *dnd) on_drag_event(x, y int) (err error) {
|
||||
switch x {
|
||||
case 4:
|
||||
dnd.reset_drag()
|
||||
return dnd.render_screen()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,6 +220,8 @@ func (dnd *dnd) run_loop() (err error) {
|
|||
dnd.send_test_response(utils.IfElse(dnd.drop_status.is_remote_client, "True", "False"))
|
||||
case "DROP_URI_LIST":
|
||||
dnd.send_test_response(strings.Join(dnd.drop_status.uri_list, "|"))
|
||||
case "DRAG_ACTIVE":
|
||||
dnd.send_test_response(utils.IfElse(dnd.drag_status.active, "DRAG_ACTIVE", "DRAG_INACTIVE"))
|
||||
default:
|
||||
dnd.send_test_response("UNKNOWN TEST COMMAND: " + string(cmd.Payload))
|
||||
}
|
||||
|
|
@ -246,6 +248,8 @@ func (dnd *dnd) run_loop() (err error) {
|
|||
return dnd.on_potential_drag_start(cmd.X, cmd.Y)
|
||||
case 'E':
|
||||
return dnd.on_drag_error(cmd)
|
||||
case 'e':
|
||||
return dnd.on_drag_event(cmd.X, cmd.Y)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
20
kitty/dnd.c
20
kitty/dnd.c
|
|
@ -1424,7 +1424,7 @@ drag_start(Window *w) {
|
|||
if (img.sz != (size_t)img.width * (size_t)img.height * 4u) abrt(EINVAL);
|
||||
}
|
||||
}
|
||||
int err = start_window_drag(w);
|
||||
int err = start_window_drag(w, dnd_is_test_mode());
|
||||
if (err != 0) {
|
||||
abrt(err);
|
||||
} else {
|
||||
|
|
@ -2162,6 +2162,18 @@ dnd_test_request_drag_data(PyObject *self UNUSED, PyObject *args) {
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
dnd_test_drag_finish(PyObject *self UNUSED, PyObject *args) {
|
||||
unsigned long long window_id; int canceled_by_user; int errcode = 0;
|
||||
if (!PyArg_ParseTuple(args, "Kp|i", &window_id, &canceled_by_user, &errcode)) return NULL;
|
||||
Window *w = window_for_window_id((id_type)window_id);
|
||||
if (!w) { PyErr_SetString(PyExc_ValueError, "Window not found"); return NULL; }
|
||||
global_state.drag_source.was_canceled = canceled_by_user;
|
||||
if (!errcode) drag_notify(w, DRAG_NOTIFY_FINISHED);
|
||||
cancel_drag(w, errcode);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
dnd_test_drag_notify(PyObject *self UNUSED, PyObject *args) {
|
||||
// Call drag_notify with a specific type for testing the protocol output.
|
||||
|
|
@ -2173,7 +2185,7 @@ dnd_test_drag_notify(PyObject *self UNUSED, PyObject *args) {
|
|||
int type;
|
||||
const char *accepted_mime = NULL;
|
||||
int action = 0, was_canceled = 0;
|
||||
if (!PyArg_ParseTuple(args, "Ki|sii", &window_id, &type, &accepted_mime, &action, &was_canceled)) return NULL;
|
||||
if (!PyArg_ParseTuple(args, "Ki|sip", &window_id, &type, &accepted_mime, &action, &was_canceled)) return NULL;
|
||||
Window *w = window_for_window_id((id_type)window_id);
|
||||
if (!w) { PyErr_SetString(PyExc_ValueError, "Window not found"); return NULL; }
|
||||
if (type < 0 || type > 3) { PyErr_SetString(PyExc_ValueError, "Invalid type"); return NULL; }
|
||||
|
|
@ -2229,6 +2241,9 @@ dnd_test_probe_state(PyObject *self UNUSED, PyObject *args) {
|
|||
if (strcmp(q, "drop_getting_data_for_mime") == 0) {
|
||||
return PyUnicode_FromString(w->drop.getting_data_for_mime ? w->drop.getting_data_for_mime : "");
|
||||
}
|
||||
if (strcmp(q, "can_offer") == 0) {
|
||||
return Py_NewRef(w->drag_source.can_offer ? Py_True : Py_False);
|
||||
}
|
||||
if (strcmp(q, "drag_operations") == 0) {
|
||||
return PyLong_FromLong((long)w->drag_source.allowed_operations);
|
||||
}
|
||||
|
|
@ -2262,6 +2277,7 @@ static PyMethodDef dnd_methods[] = {
|
|||
METHODB(dnd_test_force_drag_dropped, METH_VARARGS),
|
||||
METHODB(dnd_test_request_drag_data, METH_VARARGS),
|
||||
METHODB(dnd_test_drag_notify, METH_VARARGS),
|
||||
METHODB(dnd_test_drag_finish, METH_VARARGS),
|
||||
METHODB(dnd_test_probe_state, METH_VARARGS),
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
|
|
|||
13
kitty/glfw.c
13
kitty/glfw.c
|
|
@ -3063,12 +3063,14 @@ change_drag_thumbnail(PyObject *self UNUSED, PyObject *args) {
|
|||
}
|
||||
|
||||
int
|
||||
start_window_drag(Window *w) {
|
||||
start_window_drag(Window *w, bool in_test_mode) {
|
||||
OSWindow *osw = os_window_for_kitty_window(w->id);
|
||||
if (!osw || !osw->handle) return EINVAL;
|
||||
// Deny the drag start if mouse is not still pressed and over the originating window
|
||||
if (!osw->mouse_button_pressed[GLFW_MOUSE_BUTTON_LEFT]) return EPERM;
|
||||
if (global_state.mouse_hover_in_window != global_state.drag_source.from_window) return EPERM;
|
||||
if (!osw || (!in_test_mode && !osw->handle)) return EINVAL;
|
||||
if (!in_test_mode) {
|
||||
// Deny the drag start if mouse is not still pressed and over the originating window
|
||||
if (!osw->mouse_button_pressed[GLFW_MOUSE_BUTTON_LEFT]) return EPERM;
|
||||
if (global_state.mouse_hover_in_window != global_state.drag_source.from_window) return EPERM;
|
||||
}
|
||||
RAII_ALLOC(GLFWDragSourceItem, items, calloc(w->drag_source.num_mimes, sizeof(GLFWDragSourceItem)));
|
||||
if (!items) return ENOMEM;
|
||||
for (size_t i = 0; i < w->drag_source.num_mimes; i++) {
|
||||
|
|
@ -3097,6 +3099,7 @@ start_window_drag(Window *w) {
|
|||
global_state.drag_source.from_window = w->id;
|
||||
global_state.drag_source.from_os_window = osw->id;
|
||||
global_state.drag_source.thumbnail_idx = w->drag_source.img_idx < num_images ? (int)w->drag_source.img_idx : -1;
|
||||
if (in_test_mode) return 0;
|
||||
int ret = glfwStartDrag(osw->handle, items, w->drag_source.num_mimes, thumbnail.pixels ? &thumbnail : NULL, w->drag_source.allowed_operations, true);
|
||||
if (ret != 0) free_drag_source();
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -639,6 +639,6 @@ void register_mimes_for_drop(OSWindow *w, const char **mimes, size_t sz);
|
|||
void request_drop_data(OSWindow *w, id_type wid, const char* mime);
|
||||
void cancel_current_drag_source(void);
|
||||
bool change_drag_image(int idx);
|
||||
int start_window_drag(Window *w);
|
||||
int start_window_drag(Window *w, bool in_test_mode);
|
||||
int notify_drag_data_ready(id_type os_window_id, const char *mime_type);
|
||||
BackgroundImage* background_image_for_os_window(OSWindow *w);
|
||||
|
|
|
|||
|
|
@ -337,8 +337,10 @@ class PTY:
|
|||
def __init__(
|
||||
self, argv=None, rows=25, columns=80, scrollback=100, cell_width=10, cell_height=20,
|
||||
cwd=None, env=None, stdin_fd=None, stdout_fd=None, needs_da1=True, window_id=0,
|
||||
log_data_flow=False,
|
||||
):
|
||||
self.is_child = False
|
||||
self.log_data_flow = log_data_flow
|
||||
if isinstance(argv, str):
|
||||
argv = shlex.split(argv)
|
||||
self.write_buf = b''
|
||||
|
|
@ -423,6 +425,8 @@ class PTY:
|
|||
def write_to_child(self, data, flush=False):
|
||||
if isinstance(data, str):
|
||||
data = data.encode('utf-8')
|
||||
if self.log_data_flow:
|
||||
print('t -> c:', data)
|
||||
self.write_buf += data
|
||||
if flush:
|
||||
self.process_input_from_child(0)
|
||||
|
|
@ -446,6 +450,8 @@ class PTY:
|
|||
data = os.read(self.master_fd, io.DEFAULT_BUFFER_SIZE)
|
||||
bytes_read += len(data)
|
||||
self.received_bytes += data
|
||||
if self.log_data_flow:
|
||||
print('c -> t:', data)
|
||||
parse_bytes(self.screen, data)
|
||||
return bytes_read
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ from kitty.fast_data_types import (
|
|||
dnd_set_test_write_func,
|
||||
dnd_test_cleanup_fake_window,
|
||||
dnd_test_create_fake_window,
|
||||
dnd_test_drag_finish,
|
||||
dnd_test_fake_drop_data,
|
||||
dnd_test_fake_drop_event,
|
||||
dnd_test_probe_state,
|
||||
|
|
@ -328,10 +329,29 @@ class TestDnDKitten(BaseTest):
|
|||
f.write(os.urandom(1113))
|
||||
create_fs(self.src_data_dir)
|
||||
self.finish_setup(cli_args=(f'--drag=image/png:{img_drag_path}', self.src_data_dir)) # )))
|
||||
with self.subTest(remote=False):
|
||||
self.dnd_kitten_drag(False, img_drag_path)
|
||||
self.dnd_kitten_drag(False, img_drag_path)
|
||||
self.exit_kitten()
|
||||
|
||||
def dnd_kitten_drag(self, remote_client, img_drop_path):
|
||||
# self.pty.log_data_flow = True
|
||||
copy, move = self.get_button_geometry()
|
||||
dnd_test_start_drag_offer(self.capture.window_id, 1, 1)
|
||||
self.wait_for_state('drag_operations', 3)
|
||||
self.wait_for_state('can_offer', True)
|
||||
self.wait_for_state('drag_operations', 0)
|
||||
def wait_for_drag_active(active=True):
|
||||
self.send_dnd_command_to_kitten('DRAG_ACTIVE')
|
||||
self.wait_for_responses('DRAG_ACTIVE' if active else 'DRAG_INACTIVE')
|
||||
def start_drag(x, y, expected):
|
||||
dnd_test_start_drag_offer(self.capture.window_id, x, y)
|
||||
wait_for_drag_active()
|
||||
self.wait_for_state('drag_operations', expected)
|
||||
def end_drag(canceled=True):
|
||||
dnd_test_drag_finish(self.capture.window_id, canceled)
|
||||
wait_for_drag_active(False)
|
||||
self.wait_for_state('drag_operations', 0)
|
||||
start_drag(1, 1, 3)
|
||||
self.assertEqual(set(self.probe_state('drag_mimes')), {'image/png', 'text/uri-list'})
|
||||
end_drag()
|
||||
start_drag(copy[0] + 1, copy[1] + 1, 1)
|
||||
end_drag()
|
||||
start_drag(move[0] + 1, move[1] + 1, 2)
|
||||
end_drag()
|
||||
|
|
|
|||
|
|
@ -672,7 +672,7 @@ func (self *Loop) DrawSizedText(text string, spec SizedText) {
|
|||
func (self *Loop) QueueDnDData(cmd DndCommand) IdType {
|
||||
b := strings.Builder{}
|
||||
b.Grow(64)
|
||||
as_base64 := cmd.Type == 'r'
|
||||
as_base64 := cmd.Type == 'r' || cmd.Type == 'p'
|
||||
fmt.Fprintf(&b, "\x1b]%d;t=%c", kitty.DndCode, cmd.Type)
|
||||
add := func(key byte, val int) {
|
||||
if val != 0 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue