From 55425e2e75436038171e04676fa71e26c07de65c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 8 Jun 2026 11:22:54 +0530 Subject: [PATCH] Show secure input indicator on active tab --- docs/changelog.rst | 5 +++++ kitty/cocoa_window.m | 7 +++++++ kitty/options/definition.py | 4 +++- kitty/tab_bar.py | 6 +++++- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 76f20785c..d818deeb8 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -173,6 +173,11 @@ consumption to do the same tasks. Detailed list of changes ------------------------------------- +0.50.0 [future] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- macOS: Show a key symbol on the active tab if the macOS Secure Input feature is enabled + 0.47.2 [2026-06-07] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/kitty/cocoa_window.m b/kitty/cocoa_window.m index d688ed1ec..403acf821 100644 --- a/kitty/cocoa_window.m +++ b/kitty/cocoa_window.m @@ -1412,6 +1412,12 @@ cocoa_clear_dock_badge_if_set(void) { // }}} +static PyObject* +cocoa_is_secure_input_enabled(PyObject *self UNUSED, PyObject *args UNUSED) { + SecureKeyboardEntryController *k = [SecureKeyboardEntryController sharedInstance]; + return Py_NewRef(k.isDesired ? Py_True : Py_False); +} + static PyObject* cocoa_get_machine_id(PyObject *self UNUSED, PyObject *args UNUSED) { static char ans[1024] = {0}; @@ -1439,6 +1445,7 @@ static PyMethodDef module_methods[] = { {"cocoa_play_system_sound_by_id_async", play_system_sound_by_id_async, METH_O, ""}, {"cocoa_get_lang", (PyCFunction)cocoa_get_lang, METH_NOARGS, ""}, {"cocoa_get_machine_id", (PyCFunction)cocoa_get_machine_id, METH_NOARGS, ""}, + {"cocoa_is_secure_input_enabled", (PyCFunction)cocoa_is_secure_input_enabled, METH_NOARGS, ""}, {"cocoa_set_global_shortcut", (PyCFunction)cocoa_set_global_shortcut, METH_VARARGS, ""}, {"cocoa_send_notification", (PyCFunction)(void(*)(void))cocoa_send_notification, METH_VARARGS | METH_KEYWORDS, ""}, {"cocoa_remove_delivered_notification", (PyCFunction)cocoa_remove_delivered_notification, METH_O, ""}, diff --git a/kitty/options/definition.py b/kitty/options/definition.py index 66545faf4..5b0d1a573 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -1753,7 +1753,7 @@ A value of zero means that no limit is applied. ''' ) -opt('tab_title_template', '"{fmt.fg.red}{bell_symbol}{activity_symbol}{fmt.fg.tab}{tab.last_focused_progress_percent}{title}"', +opt('tab_title_template', '"{fmt.fg.red}{bell_symbol}{activity_symbol}{secure_input_symbol}{fmt.fg.tab}{tab.last_focused_progress_percent}{title}"', option_type='tab_title_template', long_text=''' A template to render the tab title. The default just renders the title with @@ -1776,6 +1776,8 @@ use :code:`{sup.index}`. All data available is: The number of windows in the tab. :code:`num_window_groups` The number of window groups (a window group is a window and all of its overlay windows) in the tab. +:code:`secure_input_symbol` + A key symbol when secure input is enabled on macOS and the tab is the active tab, empty otherwise. :code:`tab.active_wd` The working directory of the currently active window in the tab (expensive, requires syscall). Use :code:`tab.active_oldest_wd` to get diff --git a/kitty/tab_bar.py b/kitty/tab_bar.py index ccc121b3b..0db2b8c10 100644 --- a/kitty/tab_bar.py +++ b/kitty/tab_bar.py @@ -12,7 +12,7 @@ from typing import ( ) from .borders import Border, BorderColor -from .constants import config_dir +from .constants import config_dir, is_macos from .fast_data_types import ( BOTTOM_EDGE, DECAWM, @@ -35,6 +35,8 @@ from .types import WindowGeometry, run_once from .typing_compat import EdgeLiteral, PowerlineStyle from .utils import color_as_int, log_error, sgr_sanitizer_pat +if is_macos: + from .fast_data_types import cocoa_is_secure_input_enabled # type: ignore class TabBarData(NamedTuple): title: str @@ -268,11 +270,13 @@ def apply_title_template(draw_data: DrawData, tab: TabBarData, index: int, max_t if tab.tab_id < 0: return tab.title # synthetic tab — render title literally, skip user template ta = TabAccessor(tab.tab_id) + si = ('🔑' if cocoa_is_secure_input_enabled() else '') if is_macos and tab.is_active else '' data = { 'index': index, 'layout_name': tab.layout_name, 'num_windows': tab.num_windows, 'num_window_groups': tab.num_window_groups, + 'secure_input_symbol': si, 'title': tab.title, 'tab': ta, }