Allow focusing previously active OS windows via nth_os_window

Fixes #7009
Fixes #7008
This commit is contained in:
Kovid Goyal 2024-01-18 07:54:15 +05:30
parent 5e934c081e
commit 9b5f665218
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
4 changed files with 47 additions and 4 deletions

View file

@ -54,6 +54,8 @@ Detailed list of changes
- A new action :ac:`send_key` to simplify mapping key presses to other keys without needing :ac:`send_text`
- Allow focusing previously active OS windows via :ac:`nth_os_window` (:pull:`7009`)
- Wayland: Fix a regression in the previous release that broke copying to clipboard under wl-roots based compositors in some circumstances
(:iss:`6890`)

View file

@ -94,6 +94,7 @@ from .fast_data_types import (
is_modifier_key,
last_focused_os_window_id,
mark_os_window_for_close,
os_window_focus_counters,
os_window_font_size,
patch_global_colors,
redirect_mouse_handling,
@ -1705,12 +1706,37 @@ class Boss:
text = '\n'.join(urls)
w.paste_text(text)
@ac('win', 'Focus the nth OS window')
@ac('win', '''
Focus the nth OS window if positive or the previously active OS windows if negative. When the number is larger
than the number of OS windows focus the last OS window. A value of zero will refocus the currently focused OS window,
this is useful if focus is not on any kitty OS window at all, however, it will only work if the window manager
allows applications to grab focus. For example::
# focus the previously active OS window
map ctrl+p nth_window -1
# focus the first OS window
map ctrl+1 nth_window 0
''')
def nth_os_window(self, num: int = 1) -> None:
if self.os_window_map and num > 0:
ids = list(self.os_window_map.keys())
if not self.os_window_map:
return
if num == 0:
os_window_id = current_focused_os_window_id() or last_focused_os_window_id()
focus_os_window(os_window_id, True)
elif num > 0:
ids = tuple(self.os_window_map.keys())
os_window_id = ids[min(num, len(ids)) - 1]
focus_os_window(os_window_id, True)
elif num < 0:
fc_map = os_window_focus_counters()
s = sorted(fc_map.keys(), key=fc_map.__getitem__, reverse=True)
if not s:
return
try:
os_window_id = s[num-1]
except IndexError:
os_window_id = s[0]
focus_os_window(os_window_id, True)
@ac('win', 'Close the currently active OS Window')
def close_os_window(self) -> None:

View file

@ -1557,3 +1557,4 @@ def base64_decode(src: Union[bytes,str]) -> bytes: ...
def cocoa_recreate_global_menu() -> None: ...
def cocoa_clear_global_shortcuts() -> None: ...
def update_pointer_shape(os_window_id: int) -> None: ...
def os_window_focus_counters() -> Dict[int, int]: ...

View file

@ -116,7 +116,6 @@ last_focused_os_window_id(void) {
return ans;
}
static id_type
current_focused_os_window_id(void) {
for (size_t i = 0; i < global_state.num_os_windows; i++) {
@ -1327,10 +1326,25 @@ KKK(set_active_window)
KII(swap_tabs)
KK5I(add_borders_rect)
static PyObject*
os_window_focus_counters(PyObject *self UNUSED, PyObject *args UNUSED) {
RAII_PyObject(ans, PyDict_New());
for (size_t i = 0; i < global_state.num_os_windows; i++) {
OSWindow *w = &global_state.os_windows[i];
RAII_PyObject(key, PyLong_FromUnsignedLongLong(w->id));
RAII_PyObject(val, PyLong_FromUnsignedLongLong(w->last_focused_counter));
if (!key || !val) return NULL;
if (PyDict_SetItem(ans, key, val) != 0) return NULL;
}
Py_INCREF(ans);
return ans;
}
#define M(name, arg_type) {#name, (PyCFunction)name, arg_type, NULL}
#define MW(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL}
static PyMethodDef module_methods[] = {
M(os_window_focus_counters, METH_NOARGS),
MW(update_pointer_shape, METH_VARARGS),
MW(current_os_window, METH_NOARGS),
MW(next_window_id, METH_NOARGS),