Implement drop leaving window
This commit is contained in:
parent
fba67322d6
commit
111b35b6a7
6 changed files with 49 additions and 8 deletions
|
|
@ -63,6 +63,12 @@ list of MIME types that are available for dropping. To avoid overhead, the
|
|||
terminal should only send this list for the first move event and subsequently
|
||||
only if the list changes.
|
||||
|
||||
When the drag leaves the window, the terminal will send the same event but
|
||||
with ``x, y = -1, -1`` to indicate that the drag has left the window. For such
|
||||
events the list of MIME types must be empty. Note that the terminal must never
|
||||
send negative cell co-ordinates for any other reason.
|
||||
|
||||
|
||||
Metadata reference
|
||||
---------------------------
|
||||
|
||||
|
|
@ -85,8 +91,8 @@ Key Value Default Description
|
|||
have it set to the same value.
|
||||
**Keys for location**
|
||||
-----------------------------------------------------------
|
||||
``x`` Positive integer ``0`` Cell x-coordinate origin is 0, 0 at top left of screen
|
||||
``y`` Positive integer ``0`` Cell y-coordinate origin is 0, 0 at top left of screen
|
||||
``x`` Integer ``0`` Cell x-coordinate origin is 0, 0 at top left of screen
|
||||
``y`` Integer ``0`` Cell y-coordinate origin is 0, 0 at top left of screen
|
||||
``X`` Integer ``0`` Pixel x-coordinate origin is 0, 0 at top left of screen
|
||||
``Y`` Integer ``0`` Pixel y-coordinate origin is 0, 0 at top left of screen
|
||||
======= ==================== ========= =================
|
||||
|
|
|
|||
25
kitty/dnd.c
25
kitty/dnd.c
|
|
@ -44,11 +44,18 @@ string_arrays_cmp(const char **a, size_t an, const char **b, size_t bn) {
|
|||
}
|
||||
|
||||
static size_t
|
||||
send_payload_to_child(id_type id, const char *header, size_t header_sz, const char *data, size_t data_sz) {
|
||||
send_payload_to_child(id_type id, const char *header, size_t header_sz, const char *data, const size_t data_sz) {
|
||||
size_t offset = 0;
|
||||
char buf[4096 + 1024];
|
||||
memcpy(buf, header, header_sz);
|
||||
buf[header_sz++] = ':'; buf[header_sz++] = 'm'; buf[header_sz++] = '=';
|
||||
if (!data_sz) {
|
||||
buf[header_sz++] = 0x1b; buf[header_sz++] = '\\';
|
||||
bool found, too_much_data;
|
||||
schedule_write_to_child_if_possible(id, buf, header_sz, &found, &too_much_data);
|
||||
if (too_much_data) return 0;
|
||||
return 1;
|
||||
}
|
||||
while (offset < data_sz) {
|
||||
size_t chunk = data_sz - offset;
|
||||
size_t p = header_sz;
|
||||
|
|
@ -79,7 +86,8 @@ flush_pending(id_type id, PendingData *pending) {
|
|||
}
|
||||
break;
|
||||
} else {
|
||||
free(e->buf);
|
||||
if (!e->data_sz && !written) break;
|
||||
free(e->buf); zero_at_ptr(e);
|
||||
remove_i_from_array(pending->items, 0, pending->count);
|
||||
}
|
||||
}
|
||||
|
|
@ -90,7 +98,7 @@ static void
|
|||
queue_payload_to_child(id_type id, PendingData *pending, const char *header, size_t header_sz, const char *data, size_t data_sz) {
|
||||
size_t offset = 0;
|
||||
if (flush_pending(id, pending)) offset = send_payload_to_child(id, header, header_sz, data, data_sz);
|
||||
if (offset < data_sz) {
|
||||
if (offset < data_sz || (!offset && !data_sz)) {
|
||||
ensure_space_for(pending, items, PendingEntry, pending->count + 1, capacity, 32, true);
|
||||
char *buf = malloc(header_sz + data_sz - offset);
|
||||
if (!buf) fatal("Out of memory");
|
||||
|
|
@ -145,3 +153,14 @@ drop_move_on_child(Window *w, const char** mimes, size_t num_mimes) {
|
|||
schedule_write_to_child_if_possible(w->id, buf, header_size, &found, &too_much_data);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
drop_left_child(Window *w) {
|
||||
w->drop.hovered = false;
|
||||
drop_free_offered_mimes(w);
|
||||
if (w->drop.allowed) {
|
||||
char buf[128];
|
||||
int header_size = snprintf(buf, sizeof(buf), "\x1b]%d;i=%u:t=m:x=-1:y=-1", DND_CODE, w->drop.client_id);
|
||||
queue_payload_to_child(w->id, &w->drop.pending, buf, header_size, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,4 +9,5 @@
|
|||
#include "state.h"
|
||||
|
||||
void drop_move_on_child(Window *w, const char **mimes, size_t num_mimes);
|
||||
void drop_left_child(Window *w);
|
||||
void drop_free_data(Window *w);
|
||||
|
|
|
|||
17
kitty/glfw.c
17
kitty/glfw.c
|
|
@ -796,13 +796,17 @@ on_drop(GLFWwindow *window, GLFWDropEvent *ev) {
|
|||
if (!set_callback_window(window)) return;
|
||||
OSWindow *os_window = global_state.callback_os_window;
|
||||
Window *w = NULL;
|
||||
bool is_kitty_ui_drag = false;
|
||||
for (size_t i = 0; i < ev->num_mimes; i++) {
|
||||
if (is_droppable_mime(ev->mimes[i]) >= TAB_DRAG_MIME_NUMBER) { is_kitty_ui_drag = true; break;}
|
||||
}
|
||||
switch (ev->type) {
|
||||
case GLFW_DROP_ENTER:
|
||||
case GLFW_DROP_MOVE:
|
||||
os_window->last_drag_event.x = (int)(ev->xpos * os_window->viewport_x_ratio);
|
||||
os_window->last_drag_event.y = (int)(ev->ypos * os_window->viewport_y_ratio);
|
||||
on_mouse_position_update(ev->xpos, ev->ypos);
|
||||
if (global_state.mouse_hover_in_window && (w = window_for_window_id(global_state.mouse_hover_in_window)) && w->drop.allowed) {
|
||||
if (!is_kitty_ui_drag && global_state.mouse_hover_in_window && (w = window_for_window_id(global_state.mouse_hover_in_window)) && w->drop.allowed) {
|
||||
drop_move_on_child(w, ev->mimes, ev->num_mimes);
|
||||
return;
|
||||
}
|
||||
|
|
@ -811,9 +815,18 @@ on_drop(GLFWwindow *window, GLFWDropEvent *ev) {
|
|||
ev->from_self ? Py_True : Py_False, Py_False);
|
||||
/* fallthrough */
|
||||
case GLFW_DROP_STATUS_UPDATE:
|
||||
update_allowed_mimes_for_drop(ev);
|
||||
if (is_kitty_ui_drag) update_allowed_mimes_for_drop(ev);
|
||||
else {
|
||||
}
|
||||
break;
|
||||
case GLFW_DROP_LEAVE:
|
||||
for (size_t tc = 0; tc < os_window->num_tabs; tc++) {
|
||||
Tab *t = os_window->tabs + tc;
|
||||
for (size_t i = 0; i < t->num_windows; i++) {
|
||||
Window *w = t->windows + i;
|
||||
if (w->drop.hovered) drop_left_child(w);
|
||||
}
|
||||
}
|
||||
call_boss(on_drop_move, "KiiOO",
|
||||
os_window->id, os_window->last_drag_event.x, os_window->last_drag_event.y,
|
||||
ev->from_self ? Py_True : Py_False, Py_True);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "state.h"
|
||||
#include "screen.h"
|
||||
#include "charsets.h"
|
||||
#include "dnd.h"
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include "glfw-wrapper.h"
|
||||
|
|
@ -179,6 +180,7 @@ set_currently_hovered_window(id_type window_id, int modifiers) {
|
|||
if (left_window) {
|
||||
if (left_window->scrollbar.is_hovering) update_scrollbar_hover_state(left_window, false);
|
||||
if (left_window->render_data.screen) screen_mark_url(left_window->render_data.screen, 0, 0, 0, 0);
|
||||
if (left_window->drop.hovered) drop_left_child(left_window);
|
||||
int sz = encode_mouse_event(left_window, 0, LEAVE, modifiers);
|
||||
if (sz > 0) {
|
||||
mouse_event_buf[sz] = 0;
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ typedef struct ClickQueue {
|
|||
} ClickQueue;
|
||||
|
||||
typedef struct MousePosition {
|
||||
unsigned int cell_x, cell_y;
|
||||
unsigned cell_x, cell_y;
|
||||
double global_x, global_y;
|
||||
bool in_left_half_of_cell;
|
||||
} MousePosition;
|
||||
|
|
|
|||
Loading…
Reference in a new issue