diff --git a/kitty/boss.py b/kitty/boss.py index 3a70eae4d..dac06045a 100755 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -177,7 +177,7 @@ class VisualSelect: for wid in self.window_ids: w = boss.window_id_map.get(wid) if w is not None: - w.screen.set_window_number() + w.screen.set_window_char() return boss @@ -867,6 +867,7 @@ class Boss: choose_msg: str, only_window_ids: Container[int] = () ) -> None: + import string self.cancel_current_visual_select() tm = tab.tab_manager_ref() if tm is not None: @@ -877,22 +878,24 @@ class Boss: return pending_sequences: SubSequenceMap = {} fmap = get_name_to_functional_number_map() - num = 0 + alphabet = '0' + string.ascii_uppercase for idx, window in tab.windows.iter_windows_with_number(only_visible=True): if only_window_ids and window.id not in only_window_ids: continue ac = KeyAction('visual_window_select_action_trigger', (window.id,)) - num = idx + 1 - is_last = num == 10 - if is_last: - num = 0 - window.screen.set_window_number(num) + if idx >= 9: + num = idx - 9 + if num >= len(alphabet): + break + ch = alphabet[num] + else: + ch = str(idx + 1) + window.screen.set_window_char(ch) self.current_visual_select.window_ids.append(window.id) for mods in (0, GLFW_MOD_CONTROL, GLFW_MOD_CONTROL | GLFW_MOD_SHIFT, GLFW_MOD_SUPER, GLFW_MOD_ALT, GLFW_MOD_SHIFT): - pending_sequences[(SingleKey(mods=mods, key=ord(str(num))),)] = ac - pending_sequences[(SingleKey(mods=mods, key=fmap[f'KP_{num}']),)] = ac - if is_last: - break + pending_sequences[(SingleKey(mods=mods, key=ord(ch.lower())),)] = ac + if ch in string.digits: + pending_sequences[(SingleKey(mods=mods, key=fmap[f'KP_{ch}']),)] = ac if len(self.current_visual_select.window_ids) > 1: self.set_pending_sequences(pending_sequences, default_pending_action=KeyAction('visual_window_select_action_trigger', (0,))) redirect_mouse_handling(True) diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 1d5665f8c..c62bc74a6 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1032,7 +1032,7 @@ class Screen: def ignore_bells_for(self, duration: float = 1) -> None: pass - def set_window_number(self, num: int = -1) -> None: + def set_window_char(self, ch: str = "") -> None: pass def current_key_encoding_flags(self) -> int: diff --git a/kitty/freetype_render_ui_text.c b/kitty/freetype_render_ui_text.c index 044f9e09d..040b80cf0 100644 --- a/kitty/freetype_render_ui_text.c +++ b/kitty/freetype_render_ui_text.c @@ -502,6 +502,14 @@ static void cleanup_resize(void *p) { } #define RESIZE_AFTER_FUNCTION __attribute__((cleanup(cleanup_resize))) +static void* +report_freetype_error_for_char(int error, char ch, const char *operation) { + char buf[128]; + snprintf(buf, sizeof(buf), "Failed to %s glyph for character: %c, with error: ", operation, ch); + set_freetype_error(buf, error); + return NULL; +} + uint8_t* render_single_ascii_char_as_mask(FreeTypeRenderCtx ctx_, const char ch, size_t *result_width, size_t *result_height) { RenderCtx *ctx = (RenderCtx*)ctx_; @@ -518,10 +526,10 @@ render_single_ascii_char_as_mask(FreeTypeRenderCtx ctx_, const char ch, size_t * face->pixel_size = (FT_UInt)(face->pixel_size / ratio); if (face->pixel_size != temp.orig_sz) FT_Set_Pixel_Sizes(face->freetype, avail_height, avail_height); int error = FT_Load_Glyph(face->freetype, glyph_index, get_load_flags(face->hinting, face->hintstyle, FT_LOAD_DEFAULT)); - if (error) { PyErr_Format(PyExc_Exception, "failed to load glyph for character: %c", ch); return NULL;} + if (error) return report_freetype_error_for_char(error, ch, "load"); if (face->freetype->glyph->format != FT_GLYPH_FORMAT_BITMAP) { error = FT_Render_Glyph(face->freetype->glyph, FT_RENDER_MODE_NORMAL); - if (error) { PyErr_Format(PyExc_Exception, "failed to render glyph for character: %c", ch); return NULL;} + if (error) return report_freetype_error_for_char(error, ch, "render"); } uint8_t *rendered = NULL; switch(face->freetype->glyph->bitmap.pixel_mode) { diff --git a/kitty/screen.c b/kitty/screen.c index f9817c2ac..3792915e1 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -156,7 +156,7 @@ screen_reset(Screen *self) { if (self->overlay_line.is_active) deactivate_overlay_line(self); memset(self->main_key_encoding_flags, 0, sizeof(self->main_key_encoding_flags)); memset(self->alt_key_encoding_flags, 0, sizeof(self->alt_key_encoding_flags)); - self->display_window_number = 0; + self->display_window_char = 0; self->prompt_settings.val = 0; self->last_graphic_char = 0; self->main_savepoint.is_valid = false; @@ -2762,10 +2762,10 @@ reset_dirty(Screen *self, PyObject *a UNUSED) { } static PyObject* -set_window_number(Screen *self, PyObject *a) { - int num = -1; - if (!PyArg_ParseTuple(a, "|i", &num)) return NULL; - self->display_window_number = MAX(0, num + 1); +set_window_char(Screen *self, PyObject *a) { + const char *text = ""; + if (!PyArg_ParseTuple(a, "|s", &text)) return NULL; + self->display_window_char = text[0]; self->is_dirty = true; Py_RETURN_NONE; } @@ -3590,7 +3590,7 @@ static PyMethodDef methods[] = { MND(draw, METH_O) MND(apply_sgr, METH_O) MND(cursor_position, METH_VARARGS) - MND(set_window_number, METH_VARARGS) + MND(set_window_char, METH_VARARGS) MND(set_mode, METH_VARARGS) MND(reset_mode, METH_VARARGS) MND(reset, METH_NOARGS) diff --git a/kitty/screen.h b/kitty/screen.h index 50c518e7c..863149cdc 100644 --- a/kitty/screen.h +++ b/kitty/screen.h @@ -137,7 +137,7 @@ typedef struct { }; unsigned int val; } prompt_settings; - unsigned int display_window_number; + char display_window_char; } Screen; diff --git a/kitty/shaders.c b/kitty/shaders.c index 7a5f17011..522e1fe8b 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -584,8 +584,10 @@ draw_window_number(OSWindow *os_window, Screen *screen, GLfloat xstart, GLfloat GLfloat left = os_window->viewport_width * (xstart + 1.f) / 2.f; GLfloat right = left + os_window->viewport_width * width / 2.f; GLfloat title_bar_height = 0; - if (window->title && PyUnicode_Check(window->title)) title_bar_height = render_window_title( - os_window, screen, xstart, ystart, width, window, left, right); + size_t height_px = (size_t)(os_window->viewport_height * height / 2.f), width_px = 0; + if (window->title && PyUnicode_Check(window->title) && (height_px > (os_window->fonts_data->cell_height + 1) * 2)) { + title_bar_height = render_window_title(os_window, screen, xstart, ystart, width, window, left, right); + } if (title_bar_height > 0) { ystart -= title_bar_height; height -= title_bar_height; @@ -593,9 +595,9 @@ draw_window_number(OSWindow *os_window, Screen *screen, GLfloat xstart, GLfloat ystart -= dy / 2.f; height -= dy; // top and bottom margins xstart += dx / 2.f; width -= dx; // left and right margins GLfloat height_gl = MIN(MIN(12 * dy, height), width); - size_t height_px = (unsigned)(os_window->viewport_height * height_gl / 2.f), width_px = 0; + height_px = (size_t)(os_window->viewport_height * height_gl / 2.f); if (height_px < 4) return; - FREE_AFTER_FUNCTION uint8_t *canvas = draw_single_ascii_char('a', &width_px, &height_px); + FREE_AFTER_FUNCTION uint8_t *canvas = draw_single_ascii_char(screen->display_window_char, &width_px, &height_px); if (height_px < 4 || width_px < 4 || !canvas) return; GLfloat width_gl = 2.f * ((float)width_px) / os_window->viewport_width; left = xstart + (width - width_gl) / 2.f; @@ -845,7 +847,7 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GL if (intensity > 0.0f) draw_visual_bell_flash(intensity, xstart, ystart, w, h, screen); } - if (window && screen->display_window_number) draw_window_number(os_window, screen, xstart, ystart, w, h, window, dx, dy); + if (window && screen->display_window_char) draw_window_number(os_window, screen, xstart, ystart, w, h, window, dx, dy); } // }}}