From 398fb8d156f852371bfafcfec18b32a62daa3627 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Apr 2026 05:43:04 +0000 Subject: [PATCH] Move text width calculation into draw_window_title to avoid double CSI stripping Refactored so text_width_for_single_line is called inside draw_window_title after CSI stripping, avoiding stripping the same text twice. The standalone text_width_for_single_line wrapper is removed; draw_window_title now accepts a size_t *actual_width output parameter that, when non-NULL, triggers text width calculation and width reduction. Agent-Logs-Url: https://github.com/kovidgoyal/kitty/sessions/a70cccb9-332a-4f7b-81f8-8cbeb7ed2c26 Co-authored-by: kovidgoyal <1308621+kovidgoyal@users.noreply.github.com> --- kitty/glfw.c | 44 ++++++++++++++++++-------------------------- kitty/shaders.c | 2 +- kitty/state.h | 3 +-- 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/kitty/glfw.c b/kitty/glfw.c index d72454ddd..e7c502a1b 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -1154,19 +1154,17 @@ apple_url_open_callback(const char* url) { bool -draw_window_title(double font_sz_pts UNUSED, double ydpi UNUSED, const char *text, color_type fg, color_type bg, uint8_t *output_buf, size_t width, size_t height) { +draw_window_title(double font_sz_pts UNUSED, double ydpi UNUSED, const char *text, color_type fg, color_type bg, uint8_t *output_buf, size_t width, size_t height, size_t *actual_width) { static char buf[2048]; strip_csi_(text, buf, arraysz(buf)); + if (actual_width) { + size_t text_w = cocoa_text_width_for_single_line(buf, height); + if (text_w > 0 && text_w < width) width = text_w; + *actual_width = width; + } return cocoa_render_line_of_text(buf, fg, bg, output_buf, width, height); } -size_t -text_width_for_single_line(double font_sz_pts UNUSED, double ydpi UNUSED, const char *text, size_t height) { - static char buf[2048]; - strip_csi_(text, buf, arraysz(buf)); - return cocoa_text_width_for_single_line(buf, height); -} - uint8_t* draw_single_ascii_char(const char ch, size_t *result_width, size_t *result_height) { @@ -1211,13 +1209,18 @@ draw_text_callback(GLFWwindow *window, const char *text, uint32_t fg, uint32_t b } bool -draw_window_title(double font_sz_pts, double ydpi, const char *text, color_type fg, color_type bg, uint8_t *output_buf, size_t width, size_t height) { +draw_window_title(double font_sz_pts, double ydpi, const char *text, color_type fg, color_type bg, uint8_t *output_buf, size_t width, size_t height, size_t *actual_width) { FreeTypeRenderCtx ctx; if (!(ctx = freetype_render_ctx(false))) return false; static char buf[2048]; strip_csi_(text, buf, arraysz(buf)); unsigned px_sz = (unsigned)(font_sz_pts * ydpi / 72.); px_sz = MIN(px_sz, 3 * height / 4); + if (actual_width) { + size_t text_w = freetype_text_width_for_single_line(ctx, buf, px_sz); + if (text_w > 0 && text_w < width) width = text_w; + *actual_width = width; + } #define RGB2BGR(x) (x & 0xFF000000) | ((x & 0xFF0000) >> 16) | (x & 0x00FF00) | ((x & 0x0000FF) << 16) bool ok = render_single_line(ctx, buf, px_sz, RGB2BGR(fg), RGB2BGR(bg), output_buf, width, height, 0, 0, 0, false); #undef RGB2BGR @@ -1225,17 +1228,6 @@ draw_window_title(double font_sz_pts, double ydpi, const char *text, color_type return ok; } -size_t -text_width_for_single_line(double font_sz_pts, double ydpi, const char *text, size_t height) { - FreeTypeRenderCtx ctx; - if (!(ctx = freetype_render_ctx(false))) return 0; - static char buf[2048]; - strip_csi_(text, buf, arraysz(buf)); - unsigned px_sz = (unsigned)(font_sz_pts * ydpi / 72.); - px_sz = MIN(px_sz, 3 * height / 4); - return freetype_text_width_for_single_line(ctx, buf, px_sz); -} - uint8_t* draw_single_ascii_char(const char ch, size_t *result_width, size_t *result_height) { FreeTypeRenderCtx ctx; @@ -3109,17 +3101,17 @@ draw_single_line_of_text(PyObject *self UNUSED, PyObject *args) { 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 + padding_y; - if (max_width) { - size_t text_w = text_width_for_single_line(font_sz_pts, ydpi, text, height); - if (text_w > 0 && text_w < (size_t)width) width = (int)text_w; - } size_t buf_sz = (size_t)width * height * 4; RAII_PyObject(ans, PyBytes_FromStringAndSize(NULL, buf_sz)); if (!ans) return NULL; - if (!draw_window_title(font_sz_pts, ydpi, text, fg, bg, (uint8_t*)PyBytes_AS_STRING(ans), width, height)) { + size_t actual_width = width; + if (!draw_window_title(font_sz_pts, ydpi, text, fg, bg, (uint8_t*)PyBytes_AS_STRING(ans), width, height, max_width ? &actual_width : NULL)) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, "Failed to render text"); return NULL; } - return Py_BuildValue("Oi", ans, width); + if (actual_width < (size_t)width) { + if (_PyBytes_Resize(&ans, actual_width * height * 4) < 0) return NULL; + } + return Py_BuildValue("Oi", ans, (int)actual_width); } static bool diff --git a/kitty/shaders.c b/kitty/shaders.c index 51f2c2c58..2d50e4d49 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -845,7 +845,7 @@ render_a_bar(const UIRenderData *ui, WindowBarData *bar, PyObject *title, bool a static char titlebuf[2048] = {0}; if (!title) return 0; snprintf(titlebuf, arraysz(titlebuf), " %s", PyUnicode_AsUTF8(title)); - if (!draw_window_title(ui->os_window->fonts_data->font_sz_in_pts, ui->os_window->fonts_data->logical_dpi_y, titlebuf, fg, bg, bar->buf, bar_width, bar_height)) return 0; + if (!draw_window_title(ui->os_window->fonts_data->font_sz_in_pts, ui->os_window->fonts_data->logical_dpi_y, titlebuf, fg, bg, bar->buf, bar_width, bar_height, NULL)) return 0; Py_CLEAR(bar->last_drawn_title_object_id); bar->last_drawn_title_object_id = Py_NewRef(title); } diff --git a/kitty/state.h b/kitty/state.h index 79d18de09..9eae12db6 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -572,8 +572,7 @@ const char* format_mods(unsigned mods); void dispatch_pending_clicks(id_type, void*); void send_pending_click_to_window(Window*, int); void get_platform_dependent_config_values(void *glfw_window); -bool draw_window_title(double, double, const char *text, color_type fg, color_type bg, uint8_t *output_buf, size_t width, size_t height); -size_t text_width_for_single_line(double font_sz_pts, double ydpi, const char *text, size_t height); +bool draw_window_title(double, double, const char *text, color_type fg, color_type bg, uint8_t *output_buf, size_t width, size_t height, size_t *actual_width); uint8_t* draw_single_ascii_char(const char ch, size_t *result_width, size_t *result_height); bool is_os_window_fullscreen(OSWindow *); void update_ime_focus(OSWindow* osw, bool focused);