From d826265fd7d34fc4ff66a1089974dad59daabb5c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 7 May 2024 19:02:59 +0530 Subject: [PATCH] Get query terminal working again Also return current OS Window's font size --- kittens/query_terminal/main.py | 46 ++++++++++++++++++---------------- kitty/core_text.m | 8 +++++- kitty/fast_data_types.pyi | 9 ++++--- kitty/fonts.c | 16 +++++++++--- kitty/fonts/render.py | 4 +-- kitty/terminfo.py | 4 +-- kitty/window.py | 2 +- 7 files changed, 55 insertions(+), 34 deletions(-) diff --git a/kittens/query_terminal/main.py b/kittens/query_terminal/main.py index 31598d6fd..6303f00e1 100644 --- a/kittens/query_terminal/main.py +++ b/kittens/query_terminal/main.py @@ -50,7 +50,7 @@ class Query: return self.ans @staticmethod - def get_result(opts: Options) -> str: + def get_result(opts: Options, window_id: int, os_window_id: int) -> str: raise NotImplementedError() @@ -69,7 +69,7 @@ class TerminalName(Query): help_text: str = f'Terminal name (e.g. :code:`{names[0]}`)' @staticmethod - def get_result(opts: Options) -> str: + def get_result(opts: Options, window_id: int, os_window_id: int) -> str: return appname @@ -79,7 +79,7 @@ class TerminalVersion(Query): help_text: str = f'Terminal version (e.g. :code:`{str_version}`)' @staticmethod - def get_result(opts: Options) -> str: + def get_result(opts: Options, window_id: int, os_window_id: int) -> str: return str_version @@ -89,7 +89,7 @@ class AllowHyperlinks(Query): help_text: str = 'The config option :opt:`allow_hyperlinks` in :file:`kitty.conf` for allowing hyperlinks can be :code:`yes`, :code:`no` or :code:`ask`' @staticmethod - def get_result(opts: Options) -> str: + def get_result(opts: Options, window_id: int, os_window_id: int) -> str: return 'ask' if opts.allow_hyperlinks == 0b11 else ('yes' if opts.allow_hyperlinks else 'no') @@ -99,10 +99,10 @@ class FontFamily(Query): help_text: str = 'The current font\'s PostScript name' @staticmethod - def get_result(opts: Options) -> str: + def get_result(opts: Options, window_id: int, os_window_id: int) -> str: from kitty.fast_data_types import current_fonts - cf = current_fonts() - return str(cf['medium'].display_name()) + cf = current_fonts(os_window_id) + return cf['medium'].postscript_name() @query @@ -111,10 +111,10 @@ class BoldFont(Query): help_text: str = 'The current bold font\'s PostScript name' @staticmethod - def get_result(opts: Options) -> str: + def get_result(opts: Options, window_id: int, os_window_id: int) -> str: from kitty.fast_data_types import current_fonts - cf = current_fonts() - return str(cf['bold'].display_name()) + cf = current_fonts(os_window_id) + return cf['bold'].postscript_name() @query @@ -123,10 +123,10 @@ class ItalicFont(Query): help_text: str = 'The current italic font\'s PostScript name' @staticmethod - def get_result(opts: Options) -> str: + def get_result(opts: Options, window_id: int, os_window_id: int) -> str: from kitty.fast_data_types import current_fonts - cf = current_fonts() - return str(cf['italic'].display_name()) + cf = current_fonts(os_window_id) + return cf['italic'].postscript_name() @query @@ -135,20 +135,22 @@ class BiFont(Query): help_text: str = 'The current bold-italic font\'s PostScript name' @staticmethod - def get_result(opts: Options) -> str: + def get_result(opts: Options, window_id: int, os_window_id: int) -> str: from kitty.fast_data_types import current_fonts - cf = current_fonts() - return str(cf['bi'].display_name()) + cf = current_fonts(os_window_id) + return cf['bi'].postscript_name() @query class FontSize(Query): name: str = 'font_size' - help_text: str = 'The current overall font size (individual windows can have different per window font sizes)' + help_text: str = 'The current font size in pts' @staticmethod - def get_result(opts: Options) -> str: - return f'{opts.font_size:g}' + def get_result(opts: Options, window_id: int, os_window_id: int) -> str: + from kitty.fast_data_types import current_fonts + cf = current_fonts(os_window_id) + return f'{cf['font_sz_in_pts']:g}' @query @@ -157,16 +159,16 @@ class ClipboardControl(Query): help_text: str = 'The config option :opt:`clipboard_control` in :file:`kitty.conf` for allowing reads/writes to/from the clipboard' @staticmethod - def get_result(opts: Options) -> str: + def get_result(opts: Options, window_id: int, os_window_id: int) -> str: return ' '.join(opts.clipboard_control) -def get_result(name: str) -> Optional[str]: +def get_result(name: str, window_id: int, os_window_id: int) -> Optional[str]: from kitty.fast_data_types import get_options q = all_queries.get(name) if q is None: return None - return q.get_result(get_options()) + return q.get_result(get_options(), window_id, os_window_id) def do_queries(queries: Iterable[str], cli_opts: QueryTerminalCLIOptions) -> Dict[str, str]: diff --git a/kitty/core_text.m b/kitty/core_text.m index b62851519..6bc907394 100644 --- a/kitty/core_text.m +++ b/kitty/core_text.m @@ -849,8 +849,15 @@ display_name(CTFace *self) { return convert_cfstring(dn, true); } +static PyObject* +postscript_name(CTFace *self) { + return self->postscript_name ? Py_BuildValue("O", self->postscript_name) : PyUnicode_FromString(""); +} + + static PyMethodDef methods[] = { METHODB(display_name, METH_NOARGS), + METHODB(postscript_name, METH_NOARGS), METHODB(get_variable_data, METH_NOARGS), METHODB(identify_for_debug, METH_NOARGS), METHODB(get_best_name, METH_O), @@ -894,7 +901,6 @@ static PyMemberDef members[] = { MEM(family_name, T_OBJECT), MEM(path, T_OBJECT), MEM(full_name, T_OBJECT), - MEM(postscript_name, T_OBJECT), {NULL} /* Sentinel */ }; diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 75aee51ec..081a6278e 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -425,7 +425,7 @@ class Face: def __init__(self, descriptor: Optional[FontConfigPattern] = None, path: str = '', index: int = 0): ... def get_variable_data(self) -> VariableData: ... def identify_for_debug(self) -> str: ... - def display_name(self) -> str: ... + def postscript_name(self) -> str: ... class CoreTextFont(TypedDict): @@ -456,7 +456,7 @@ class CTFace: def __init__(self, descriptor: Optional[CoreTextFont] = None, path: str = ''): ... def get_variable_data(self) -> VariableData: ... def identify_for_debug(self) -> str: ... - def display_name(self) -> str: ... + def postscript_name(self) -> str: ... def coretext_all_fonts(monospaced_only: bool) -> Tuple[CoreTextFont, ...]: @@ -922,9 +922,12 @@ class CurrentFonts(TypedDict): bi: FontFace symbol: Tuple[FontFace, ...] fallback: Tuple[FontFace, ...] + font_sz_in_pts: float + logical_dpi_x: float + logical_dpi_y: float -def current_fonts() -> CurrentFonts: ... +def current_fonts(os_window_id: int = 0) -> CurrentFonts: ... def remove_window(os_window_id: int, tab_id: int, window_id: int) -> None: diff --git a/kitty/fonts.c b/kitty/fonts.c index c690799f7..e1e57208a 100644 --- a/kitty/fonts.c +++ b/kitty/fonts.c @@ -1633,11 +1633,18 @@ concat_cells(PyObject UNUSED *self, PyObject *args) { } static PyObject* -current_fonts(PYNOARG) { +current_fonts(PyObject *self UNUSED, PyObject *args) { + unsigned long long os_window_id = 0; + if (!PyArg_ParseTuple(args, "|K", &os_window_id)) return NULL; if (!num_font_groups) { PyErr_SetString(PyExc_RuntimeError, "must create font group first"); return NULL; } + FontGroup *fg = font_groups; + if (os_window_id) { + OSWindow *os_window = os_window_for_id(os_window_id); + if (!os_window) { PyErr_SetString(PyExc_KeyError, "no oswindow with the specified id exists"); return NULL; } + fg = (FontGroup*)os_window->fonts_data; + } RAII_PyObject(ans, PyDict_New()); if (!ans) return NULL; - FontGroup *fg = font_groups; #define SET(key, val) {if (PyDict_SetItemString(ans, #key, fg->fonts[val].face) != 0) { return NULL; }} SET(medium, fg->medium_font_idx); if (fg->bold_font_idx > 0) SET(bold, fg->bold_font_idx); @@ -1658,6 +1665,9 @@ current_fonts(PYNOARG) { PyTuple_SET_ITEM(ff, i, fg->fonts[fg->first_fallback_font_idx + i].face); } if (PyDict_SetItemString(ans, "fallback", ff) != 0) return NULL; +#define p(x) { RAII_PyObject(t, PyFloat_FromDouble(fg->x)); if (!t) return NULL; if (PyDict_SetItemString(ans, #x, t) != 0) return NULL; } + p(font_sz_in_pts); p(logical_dpi_x); p(logical_dpi_y); +#undef p Py_INCREF(ans); return ans; #undef SET @@ -1725,7 +1735,7 @@ static PyMethodDef module_methods[] = { METHODB(concat_cells, METH_VARARGS), METHODB(set_send_sprite_to_gpu, METH_O), METHODB(test_shape, METH_VARARGS), - METHODB(current_fonts, METH_NOARGS), + METHODB(current_fonts, METH_VARARGS), METHODB(test_render_line, METH_VARARGS), METHODB(get_fallback_font, METH_VARARGS), {NULL, NULL, 0, NULL} /* Sentinel */ diff --git a/kitty/fonts/render.py b/kitty/fonts/render.py index df4087157..b30e916ea 100644 --- a/kitty/fonts/render.py +++ b/kitty/fonts/render.py @@ -497,8 +497,8 @@ def test_render_string( cell_width, cell_height, cells = render_string(text, family, size, dpi) rgb_data = concat_cells(cell_width, cell_height, True, tuple(cells)) cf = current_fonts() - fonts = [cf['medium'].display_name()] - fonts.extend(f.display_name() for f in cf['fallback']) + fonts = [cf['medium'].postscript_name()] + fonts.extend(f.postscript_name() for f in cf['fallback']) msg = 'Rendered string {} below, with fonts: {}\n'.format(text, ', '.join(fonts)) try: print(msg) diff --git a/kitty/terminfo.py b/kitty/terminfo.py index 4bdd3055d..ddad06019 100644 --- a/kitty/terminfo.py +++ b/kitty/terminfo.py @@ -517,7 +517,7 @@ def key_as_bytes(name: str) -> bytes: return ans.encode('ascii') -def get_capabilities(query_string: str, opts: 'Options') -> Generator[str, None, None]: +def get_capabilities(query_string: str, opts: 'Options', window_id: int, os_window_id: int) -> Generator[str, None, None]: from .fast_data_types import ERROR_PREFIX def result(encoded_query_name: str, x: Optional[str] = None) -> str: @@ -533,7 +533,7 @@ def get_capabilities(query_string: str, opts: 'Options') -> Generator[str, None, elif name.startswith('kitty-query-'): from kittens.query_terminal.main import get_result name = name[len('kitty-query-'):] - rval = get_result(name) + rval = get_result(name, window_id, os_window_id) if rval is None: from .utils import log_error log_error('Unknown kitty terminfo query:', name) diff --git a/kitty/window.py b/kitty/window.py index 9f8c89e22..e38d3522f 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -1273,7 +1273,7 @@ class Window: self.refresh() def request_capabilities(self, q: str) -> None: - for result in get_capabilities(q, get_options()): + for result in get_capabilities(q, get_options(), self.id, self.os_window_id): self.screen.send_escape_code_to_child(ESC_DCS, result) def handle_remote_cmd(self, cmd: memoryview) -> None: