diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index d7136fb8d..4d47c3d12 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1063,6 +1063,12 @@ class Screen: def erase_in_display(self, how: int = 0, private: bool = False) -> None: pass + def focus_changed(self, focused: bool) -> bool: + pass + + def has_focus(self) -> bool: + pass + def set_tab_bar_render_data( os_window_id: int, xstart: float, ystart: float, dx: float, dy: float, diff --git a/kitty/screen.c b/kitty/screen.c index 9bc5c6eb1..28d2b011e 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -2525,6 +2525,24 @@ paste_bytes(Screen *self, PyObject *bytes) { Py_RETURN_NONE; } +static PyObject* +focus_changed(Screen *self, PyObject *has_focus_) { + bool previous = self->has_focus; + bool has_focus = PyObject_IsTrue(has_focus_) ? true : false; + if (has_focus != previous) { + self->has_focus = has_focus; + if (self->modes.mFOCUS_TRACKING) write_escape_code_to_child(self, CSI, has_focus ? "I" : "O"); + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; +} + +static PyObject* +has_focus(Screen *self, PyObject *args UNUSED) { + if (self->has_focus) Py_RETURN_TRUE; + Py_RETURN_FALSE; +} + WRAP2(cursor_position, 1, 1) @@ -2608,6 +2626,8 @@ static PyMethodDef methods[] = { MND(reset_callbacks, METH_NOARGS) MND(paste, METH_O) MND(paste_bytes, METH_O) + MND(focus_changed, METH_O) + MND(has_focus, METH_NOARGS) MND(copy_colors_from, METH_O) MND(set_marker, METH_VARARGS) MND(marked_cells, METH_NOARGS) diff --git a/kitty/screen.h b/kitty/screen.h index 2f26d88d4..6ed4fdd9a 100644 --- a/kitty/screen.h +++ b/kitty/screen.h @@ -121,6 +121,7 @@ typedef struct { } pending_mode; DisableLigature disable_ligatures; PyObject *marker; + bool has_focus; } Screen; diff --git a/kitty/window.py b/kitty/window.py index d313aea4b..c986801ea 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -20,7 +20,7 @@ from .config import build_ansi_color_table from .constants import ScreenGeometry, WindowGeometry, appname, wakeup from .fast_data_types import ( BGIMAGE_PROGRAM, BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM, - CELL_PROGRAM, CELL_SPECIAL_PROGRAM, CSI, DCS, DECORATION, DIM, + CELL_PROGRAM, CELL_SPECIAL_PROGRAM, DCS, DECORATION, DIM, GRAPHICS_ALPHA_MASK_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_PROGRAM, MARK, MARK_MASK, OSC, REVERSE, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, STRIKETHROUGH, TINT_PROGRAM, Screen, add_timer, add_window, @@ -493,18 +493,14 @@ class Window: if self.destroyed: return call_watchers(weakref.ref(self), 'on_focus_change', {'focused': focused}) + self.screen.focus_changed(focused) if focused: changed = self.needs_attention self.needs_attention = False - if self.screen.focus_tracking_enabled: - self.screen.send_escape_code_to_child(CSI, 'I') if changed: tab = self.tabref() if tab is not None: tab.relayout_borders() - else: - if self.screen.focus_tracking_enabled: - self.screen.send_escape_code_to_child(CSI, 'O') def title_changed(self, new_title: Optional[str]) -> None: self.child_title = sanitize_title(new_title or self.default_title)