mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-08-28 04:13:44 +00:00
When dropping, paste into window under mouse cursor rather than active window
This commit is contained in:
parent
7004911271
commit
d51dec8187
6 changed files with 59 additions and 31 deletions
|
|
@ -1384,6 +1384,10 @@ static void freeFilteredDragMimes(_GLFWwindow* window, int old_count, int new_co
|
|||
const NSPoint pos = [sender draggingLocation];
|
||||
double xpos = pos.x;
|
||||
double ypos = contentRect.size.height - pos.y;
|
||||
float xscale = 1, yscale = 1;
|
||||
_glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
|
||||
xpos *= xscale; ypos *= yscale;
|
||||
|
||||
|
||||
// Get MIME types from the dragging pasteboard
|
||||
NSPasteboard* pasteboard = [sender draggingPasteboard];
|
||||
|
|
@ -1462,6 +1466,9 @@ static void freeFilteredDragMimes(_GLFWwindow* window, int old_count, int new_co
|
|||
const NSPoint pos = [sender draggingLocation];
|
||||
double xpos = pos.x;
|
||||
double ypos = contentRect.size.height - pos.y;
|
||||
float xscale = 1, yscale = 1;
|
||||
_glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
|
||||
xpos *= xscale; ypos *= yscale;
|
||||
|
||||
// Call drag move callback with cached MIME types
|
||||
int old_count = window->ns.dragMimeCount;
|
||||
|
|
|
|||
15
glfw/wl_window.c
vendored
15
glfw/wl_window.c
vendored
|
|
@ -2473,7 +2473,8 @@ static void update_drag_state(_GLFWWaylandDataOffer *d, _GLFWwindow* window UNUS
|
|||
}
|
||||
}
|
||||
|
||||
static void drag_enter(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED, uint32_t serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y, struct wl_data_offer *id) {
|
||||
static void
|
||||
drag_enter(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED, uint32_t serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y, struct wl_data_offer *id) {
|
||||
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||
_GLFWWaylandDataOffer *d = _glfw.wl.dataOffers + i;
|
||||
if (d->id == id) {
|
||||
|
|
@ -2489,8 +2490,9 @@ static void drag_enter(void *data UNUSED, struct wl_data_device *wl_data_device
|
|||
// Call drag enter callback with writable MIME types array
|
||||
double xpos = wl_fixed_to_double(x);
|
||||
double ypos = wl_fixed_to_double(y);
|
||||
double scale = _glfwWaylandWindowScale(window);
|
||||
int mime_count = (int)d->mimes_count;
|
||||
int accepted = _glfwInputDragEvent(window, GLFW_DRAG_ENTER, xpos, ypos, d->mimes, &mime_count);
|
||||
int accepted = _glfwInputDragEvent(window, GLFW_DRAG_ENTER, scale * xpos, scale * ypos, d->mimes, &mime_count);
|
||||
|
||||
// Update drag state based on callback results
|
||||
update_drag_state(d, window, accepted, mime_count);
|
||||
|
|
@ -2505,7 +2507,8 @@ static void drag_enter(void *data UNUSED, struct wl_data_device *wl_data_device
|
|||
prune_unclaimed_data_offers();
|
||||
}
|
||||
|
||||
static void drag_leave(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED) {
|
||||
static void
|
||||
drag_leave(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED) {
|
||||
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||
if (_glfw.wl.dataOffers[i].offer_type == DRAG_AND_DROP) {
|
||||
// Find the window for this offer and call the leave callback
|
||||
|
|
@ -2562,7 +2565,8 @@ drop(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED) {
|
|||
}
|
||||
}
|
||||
|
||||
static void motion(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED, uint32_t time UNUSED, wl_fixed_t x, wl_fixed_t y) {
|
||||
static void
|
||||
motion(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED, uint32_t time UNUSED, wl_fixed_t x, wl_fixed_t y) {
|
||||
// Find the current drag offer and send motion events
|
||||
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||
_GLFWWaylandDataOffer *d = &_glfw.wl.dataOffers[i];
|
||||
|
|
@ -2572,9 +2576,10 @@ static void motion(void *data UNUSED, struct wl_data_device *wl_data_device UNUS
|
|||
if (window->wl.surface == d->surface) {
|
||||
double xpos = wl_fixed_to_double(x);
|
||||
double ypos = wl_fixed_to_double(y);
|
||||
double scale = _glfwWaylandWindowScale(window);
|
||||
// Pass the MIME types array for move events
|
||||
int mime_count = (int)d->mimes_count;
|
||||
int accepted = _glfwInputDragEvent(window, GLFW_DRAG_MOVE, xpos, ypos, d->mimes, &mime_count);
|
||||
int accepted = _glfwInputDragEvent(window, GLFW_DRAG_MOVE, scale * xpos, scale * ypos, d->mimes, &mime_count);
|
||||
|
||||
// Update drag state based on callback results
|
||||
update_drag_state(d, window, accepted, mime_count);
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ from .fast_data_types import (
|
|||
toggle_maximized,
|
||||
toggle_os_window_visibility,
|
||||
toggle_secure_input,
|
||||
viewport_for_window,
|
||||
wrapped_kitten_names,
|
||||
)
|
||||
from .key_encoding import get_name_to_functional_number_map
|
||||
|
|
@ -151,7 +152,6 @@ from .utils import (
|
|||
open_url,
|
||||
parse_address_spec,
|
||||
parse_os_window_state,
|
||||
parse_uri_list,
|
||||
platform_window_id,
|
||||
safe_print,
|
||||
sanitize_url_for_display_to_user,
|
||||
|
|
@ -1883,28 +1883,24 @@ class Boss:
|
|||
if tm is not None:
|
||||
tm.update_tab_bar_data()
|
||||
|
||||
def on_drop(self, os_window_id: int, drop: dict[str, bytes] | Exception) -> None:
|
||||
def on_drop(self, os_window_id: int, drop: dict[str, bytes] | Exception, x: int, y: int) -> None:
|
||||
if isinstance(drop, Exception):
|
||||
self.show_error(_('Drop failed'), str(drop))
|
||||
return
|
||||
tm = self.os_window_map.get(os_window_id)
|
||||
if tm is not None:
|
||||
w = tm.active_window
|
||||
if w is not None:
|
||||
text = ''
|
||||
if uri_list := drop.pop('text/uri-list', b''):
|
||||
urls = parse_uri_list(uri_list.decode('utf-8', 'replace'))
|
||||
if w.at_prompt:
|
||||
import shlex
|
||||
text = ' '.join(map(shlex.quote, urls))
|
||||
else:
|
||||
text = '\n'.join(urls)
|
||||
elif tp := drop.pop('text/plain', b''):
|
||||
text = tp.decode('utf-8', 'replace')
|
||||
elif tp := drop.pop('text/plain;charset=utf-8', b''):
|
||||
text = tp.decode('utf-8', 'replace')
|
||||
if text:
|
||||
w.paste_text(text)
|
||||
central, tab_bar = viewport_for_window(os_window_id)[:2]
|
||||
if central.left <= x < central.right and central.top <= y < central.bottom:
|
||||
if (tm := self.os_window_map.get(os_window_id)) is None or (tab := tm.active_tab) is None:
|
||||
return
|
||||
for window in tab:
|
||||
g = window.geometry
|
||||
if g.left <= x - central.left < g.right and g.top <= y - central.top < g.bottom:
|
||||
window.on_drop(drop)
|
||||
break
|
||||
elif tab_bar.left <= x < tab_bar.right and tab_bar.top <= y < central.bottom:
|
||||
if (tm := self.os_window_map.get(os_window_id)) is None:
|
||||
return
|
||||
if (tab_id := tm.tab_bar.tab_id_at(x)) and (tab := self.tab_for_id(tab_id)) and (w := tab.active_window):
|
||||
w.on_drop(drop)
|
||||
|
||||
@ac('win', '''
|
||||
Focus the nth OS window if positive or the previously active OS windows if negative. When the number is larger
|
||||
|
|
|
|||
|
|
@ -657,6 +657,9 @@ drag_callback(GLFWwindow *w, GLFWDragEventType event, double xpos, double ypos,
|
|||
switch (event) {
|
||||
case GLFW_DRAG_ENTER:
|
||||
case GLFW_DRAG_MOVE:
|
||||
global_state.callback_os_window->last_drag_event.x = (int)xpos;
|
||||
global_state.callback_os_window->last_drag_event.y = (int)ypos;
|
||||
/* fallthrough */
|
||||
case GLFW_DRAG_STATUS_UPDATE:
|
||||
if (mime_types && mime_count && *mime_count > 0) {
|
||||
// Sort MIME types by priority (descending) and keep only accepted ones
|
||||
|
|
@ -693,6 +696,8 @@ drag_callback(GLFWwindow *w, GLFWDragEventType event, double xpos, double ypos,
|
|||
}
|
||||
break;
|
||||
case GLFW_DRAG_LEAVE:
|
||||
global_state.callback_os_window->last_drag_event.x = (int)xpos;
|
||||
global_state.callback_os_window->last_drag_event.y = (int)ypos;
|
||||
break;
|
||||
}
|
||||
end:
|
||||
|
|
@ -745,8 +750,8 @@ drop_callback(GLFWwindow *w, GLFWDropData *drop) {
|
|||
RAII_PyObject(exc, PyErr_GetRaisedException());
|
||||
glfwFinishDrop(drop, GLFW_DRAG_OPERATION_COPY, true);
|
||||
if (!set_callback_window(w)) return;
|
||||
if (exc != NULL) { WINDOW_CALLBACK(on_drop, "O", exc); }
|
||||
else if (PyDict_Size(ans)) WINDOW_CALLBACK(on_drop, "O", ans);
|
||||
if (exc != NULL) { WINDOW_CALLBACK(on_drop, "Oii", exc, global_state.callback_os_window->last_drag_event.x, global_state.callback_os_window->last_drag_event.y); }
|
||||
else if (PyDict_Size(ans)) WINDOW_CALLBACK(on_drop, "Oii", ans, global_state.callback_os_window->last_drag_event.x, global_state.callback_os_window->last_drag_event.y);
|
||||
request_tick_callback();
|
||||
global_state.callback_os_window = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -342,6 +342,7 @@ typedef struct OSWindow {
|
|||
id_type last_focused_counter;
|
||||
CloseRequest close_request;
|
||||
bool is_layer_shell, hide_on_focus_loss;
|
||||
struct { int x, y; } last_drag_event;
|
||||
} OSWindow;
|
||||
|
||||
static inline float
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ from .utils import (
|
|||
log_error,
|
||||
open_cmd,
|
||||
open_url,
|
||||
parse_uri_list,
|
||||
path_from_osc7_url,
|
||||
resolve_custom_file,
|
||||
resolved_shell,
|
||||
|
|
@ -981,10 +982,6 @@ class Window:
|
|||
if update_ime_position:
|
||||
update_ime_position_for_window(self.id, True)
|
||||
|
||||
def contains(self, x: int, y: int) -> bool:
|
||||
g = self.geometry
|
||||
return g.left <= x <= g.right and g.top <= y <= g.bottom
|
||||
|
||||
def close(self) -> None:
|
||||
get_boss().mark_window_for_close(self)
|
||||
|
||||
|
|
@ -1942,6 +1939,23 @@ class Window:
|
|||
' Return the last position at which a mouse event was received by this window '
|
||||
return get_mouse_data_for_window(self.os_window_id, self.tab_id, self.id)
|
||||
|
||||
def on_drop(self, drop: dict[str, bytes]) -> None:
|
||||
text = ''
|
||||
if uri_list := drop.pop('text/uri-list', b''):
|
||||
urls = parse_uri_list(uri_list.decode('utf-8', 'replace'))
|
||||
if self.at_prompt:
|
||||
import shlex
|
||||
text = ' '.join(map(shlex.quote, urls))
|
||||
else:
|
||||
text = '\n'.join(urls)
|
||||
elif tp := drop.pop('text/plain', b''):
|
||||
text = tp.decode('utf-8', 'replace')
|
||||
elif tp := drop.pop('text/plain;charset=utf-8', b''):
|
||||
text = tp.decode('utf-8', 'replace')
|
||||
if text:
|
||||
self.paste_text(text)
|
||||
|
||||
|
||||
# Serialization {{{
|
||||
def as_dict(
|
||||
self, is_focused: bool = False, is_self: bool = False, is_active: bool = False,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue