diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 92109f464..df15b0cd2 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -3227,7 +3227,7 @@ static void drag_source_dnd_drop_performed(void *data UNUSED, struct wl_data_source *source UNUSED) { _GLFWwindow *window = _glfwWindowForId(_glfw.drag.window_id); if (window) { - GLFWDragEvent ev = {.type=GLFW_DRAG_ACTION_CHANGED}; + GLFWDragEvent ev = {.type=GLFW_DRAG_DROPPED}; _glfwInputDragSourceRequest(window, &ev); } else drag_source_cancelled(data, source); } diff --git a/kitty/boss.py b/kitty/boss.py index c5ea676bb..a48c82a93 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -1917,6 +1917,7 @@ class Boss: set_tab_being_dragged() for tm in self.all_tab_managers: tm.on_tab_drop_move(0, False, 0, 0) + tm.layout_tab_bar() # ensure tab bar is fully updated return central, tab_bar = viewport_for_window(os_window_id)[:2] if central.left <= x < central.right and central.top <= y < central.bottom: @@ -1932,6 +1933,18 @@ class Boss: 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) + def on_drag_source_finished( + self, was_dropped: bool, was_canceled: bool, accepted_mime_type: str, action: int, data: dict[str, bytes] | None + ) -> None: + if data and (tidb := data.get(f'application/net.kovidgoyal.kitty-tab-{os.getpid()}')): + set_tab_being_dragged() + for tm in self.all_tab_managers: + tm.on_tab_drop_move(0, False, 0, 0) + if not was_dropped: # detach tab into new OS Window + tab_id = int(tidb.decode()) + if (tab := self.tab_for_id(tab_id)): + self._move_tab_to(tab) + @ac('win', ''' Focus the nth OS window if positive or the previously active OS windows if negative. When the number is larger than the number of OS windows focus the last OS window. A value of zero will refocus the currently focused OS window, diff --git a/kitty/glfw.c b/kitty/glfw.c index 7a5a64591..2974a2914 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -746,6 +746,7 @@ on_drop(GLFWwindow *window, GLFWDropEvent *ev) { Py_CLEAR(global_state.drop_dest.data); if (ev->from_self) { if (global_state.drag_source.drag_data) { + global_state.drag_source.was_dropped = true; WINDOW_CALLBACK(on_drop, "OOii", global_state.drag_source.drag_data, Py_True, global_state.callback_os_window->last_drag_event.x, global_state.callback_os_window->last_drag_event.y); } else log_error("Got a drop from self but drag_source.drag_data is NULL"); @@ -804,12 +805,17 @@ drag_source_callback(GLFWwindow *window UNUSED, GLFWDragEvent *ev) { ds.accepted_mime_type = ev->mime_type ? strdup(ev->mime_type) : NULL; break; case GLFW_DRAG_ACTION_CHANGED: ds.action = ev->action; break; - case GLFW_DRAG_DROPPED: ds.was_dropped = true; break; + case GLFW_DRAG_DROPPED: + ds.was_dropped = true; + break; case GLFW_DRAG_CANCELLED: ds.was_canceled = true; /* fallthrough */ case GLFW_DRAG_FINSHED: - ds.is_active = false; + call_boss(on_drag_source_finished, "OOsiO", + ds.was_dropped ? Py_True : Py_False, ds.was_canceled ? Py_True: Py_False, + ds.accepted_mime_type ? ds.accepted_mime_type : "", + ds.action, ds.drag_data ? ds.drag_data : Py_None); free_drag_source(); break; }