diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index d109d6e94..d4a52cdcd 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1818,6 +1818,7 @@ def start_drag_with_data( operations: int = GLFW_DRAG_OPERATION_MOVE ) -> None: ... +def draw_drag_icon_title(os_window_id: int, text: str, fg: int, bg: int, width: int) -> bytes: ... def set_tab_being_dragged(tab_id: int = 0, drag_started: bool = False, x: float = 0, y: float = 0) -> None: ... def get_tab_being_dragged() -> tuple[int, bool, float, float]: ... def request_callback_with_thumbnail( diff --git a/kitty/glfw.c b/kitty/glfw.c index 201184df3..68f9ecf62 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -2759,6 +2759,28 @@ grab_keyboard(PyObject *self UNUSED, PyObject *action) { return Py_NewRef(glfwGrabKeyboard(action == Py_None ? 2 : PyObject_IsTrue(action)) ? Py_True : Py_False); } +static PyObject* +draw_drag_icon_title(PyObject *self UNUSED, PyObject *args) { + unsigned long long os_window_id; + const char *text; + unsigned int fg, bg; + int width; + if (!PyArg_ParseTuple(args, "KsIIi", &os_window_id, &text, &fg, &bg, &width)) return NULL; + OSWindow *w = os_window_for_id(os_window_id); + if (!w || !w->fonts_data) { PyErr_SetString(PyExc_KeyError, "OS Window with specified id does not exist or has no fonts data"); return NULL; } + double font_sz_pts = w->fonts_data->font_sz_in_pts; + double ydpi = w->fonts_data->logical_dpi_y; + size_t height = (size_t)w->fonts_data->fcm.cell_height + 2; // extra 2px for visual padding + size_t buf_sz = (size_t)width * height * 4; + RAII_ALLOC(uint8_t, buf, calloc(buf_sz, 1)); + if (!buf) return PyErr_NoMemory(); + if (!draw_window_title(font_sz_pts, ydpi, text, fg, bg, buf, width, height)) { + if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, "Failed to render drag icon title"); + return NULL; + } + return PyBytes_FromStringAndSize((char*)buf, buf_sz); +} + static PyObject* start_drag_with_data(PyObject *self UNUSED, PyObject *args, PyObject *kw) { static const char* kwlist[] = {"os_window_id", "data_map", "thumbnail", "width", "height", "operations", NULL}; @@ -2803,6 +2825,7 @@ static PyMethodDef module_methods[] = { METHODB(pointer_name_to_css_name, METH_O), {"create_os_window", (PyCFunction)(void (*) (void))(create_os_window), METH_VARARGS | METH_KEYWORDS, NULL}, {"start_drag_with_data", (PyCFunction)(void (*) (void))(start_drag_with_data), METH_VARARGS | METH_KEYWORDS, NULL}, + METHODB(draw_drag_icon_title, METH_VARARGS), METHODB(set_default_window_icon, METH_VARARGS), METHODB(set_os_window_icon, METH_VARARGS), METHODB(set_clipboard_data_types, METH_VARARGS), diff --git a/kitty/tabs.py b/kitty/tabs.py index 5f91058c9..f2ada74d2 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -28,6 +28,7 @@ from .fast_data_types import ( buffer_keys_in_window, current_focused_os_window_id, detach_window, + draw_drag_icon_title, get_boss, get_click_interval, get_options, @@ -57,7 +58,7 @@ from .progress import ProgressState from .tab_bar import TabBar, TabBarData, apply_title_template from .types import ac from .typing_compat import EdgeLiteral, SessionTab, SessionType, TypedDict -from .utils import cmdline_for_hold, log_error, platform_window_id, resolved_shell, shlex_split, which +from .utils import cmdline_for_hold, color_as_int, log_error, platform_window_id, resolved_shell, shlex_split, which from .window import CwdRequest, Watchers, Window, WindowCreationSpec, WindowDict, global_watchers from .window_list import WindowList @@ -1640,11 +1641,15 @@ class TabManager: # {{{ title = re.sub(r'\x1b\[.+?[a-zA-Z]', '', title).strip() # strip CSI codes ] title = replace_c0_codes_except_nl_space_tab(title.encode()).decode() title = re.sub(r'\n', ' ', title) - # TODO: Add the title to the drag icon + opts = get_options() + fg = 0xff000000 | color_as_int(opts.active_tab_foreground) + bg = 0xff000000 | color_as_int(opts.active_tab_background) + title_pixels = draw_drag_icon_title(self.os_window_id, title, fg, bg, width) + title_height = len(title_pixels) // (width * 4) drag_data = { f'application/net.kovidgoyal.kitty-tab-{os.getpid()}': str(tab.id).encode(), } - start_drag_with_data(self.os_window_id, drag_data, pixels, width, height) + start_drag_with_data(self.os_window_id, drag_data, title_pixels + pixels, width, title_height + height) break else: set_tab_being_dragged()