diff --git a/docs/changelog.rst b/docs/changelog.rst index 94d339284..fd61dc43a 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -38,6 +38,8 @@ Detailed list of changes 0.26.2 [future] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +- Allow creating :code:`overlay-main` windows, which are treated as the active window unlike normal overlays (:iss:`5392`) + - hyperlinked_grep kitten: Allow control over which parts of rg output are hyperlinked (:pull:`5428`) - Fix regression in 0.26.0 that caused launching kitty without working STDIO handles to result in high CPU usage and prewarming failing (:iss:`5444`) diff --git a/docs/glossary.rst b/docs/glossary.rst index c084f052f..f8af4a0ae 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -32,7 +32,12 @@ Glossary top of an existing kitty window, entirely covering it. Overlays are used throughout kitty, for example, to display the :ref:`the scrollback buffer `, to display :doc:`hints `, for :doc:`unicode input - ` etc. + ` etc. Normal overlays are meant for short + duration popups and so are not considered the :italic:`active window` + when determining the current working directory or getting input text for + kittens, launch commands, etc. To create an overlay considered as a + :italic:`main window` use the :code:`overlay-main` argument to + :doc:`launch`. hyperlinks Terminals can have hyperlinks, just like the internet. In kitty you can diff --git a/kitty/launch.py b/kitty/launch.py index 3785ac905..50a9ee17d 100644 --- a/kitty/launch.py +++ b/kitty/launch.py @@ -21,7 +21,7 @@ from .fast_data_types import ( ) from .options.utils import env as parse_env from .tabs import Tab, TabManager -from .types import run_once +from .types import OverlayType, run_once from .utils import ( get_editor, log_error, resolve_custom_file, set_primary_selection, which ) @@ -56,7 +56,7 @@ of the active window in the tab is used as the tab title. The special value --type type=choices default=window -choices=window,tab,os-window,overlay,background,clipboard,primary +choices=window,tab,os-window,overlay,overlay-main,background,clipboard,primary Where to launch the child process: :code:`window` @@ -71,6 +71,13 @@ Where to launch the child process: :code:`overlay` An :term:`overlay window ` covering the current active kitty window +:code:`overlay-main` + An :term:`overlay window ` covering the current active kitty window. + Unlike a plain overlay window, this window is considered as a :italic:`main` + window which means it is used as the active window for getting the current working + directory, the input text for kittens, launch commands, etc. Useful if this overlay is + intended to run for a long time as a primary window. + :code:`background` The process will be run in the :italic:`background`, without a kitty window. @@ -539,7 +546,7 @@ def launch( kw['cmd'] = final_cmd if force_window_launch and opts.type not in non_window_launch_types: opts.type = 'window' - if opts.type == 'overlay' and active: + if opts.type in ('overlay', 'overlay-main') and active: kw['overlay_for'] = active.id if opts.type == 'background': cmd = kw['cmd'] @@ -573,6 +580,8 @@ def launch( boss.set_active_window(active, switch_os_window_if_needed=True, for_keep_focus=True) if opts.logo: new_window.set_logo(opts.logo, opts.logo_position or '', opts.logo_alpha) + if opts.type == 'overlay-main': + new_window.overlay_type = OverlayType.main return new_window return None diff --git a/kitty/tabs.py b/kitty/tabs.py index 3557bafc2..93a08c49c 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -211,7 +211,7 @@ class Tab: # {{{ @property def active_window_for_cwd(self) -> Optional[Window]: - return self.windows.active_group_base + return self.windows.active_group_main @property def title(self) -> str: diff --git a/kitty/types.py b/kitty/types.py index 02baf77fe..3c12f82b0 100644 --- a/kitty/types.py +++ b/kitty/types.py @@ -1,16 +1,24 @@ #!/usr/bin/env python # License: GPLv3 Copyright: 2021, Kovid Goyal +from enum import Enum from functools import update_wrapper from typing import ( - TYPE_CHECKING, Any, Callable, Generic, NamedTuple, Tuple, TypeVar, Union, Iterator, Dict + TYPE_CHECKING, Any, Callable, Dict, Generic, Iterator, NamedTuple, Tuple, + TypeVar, Union ) + if TYPE_CHECKING: from kitty.fast_data_types import SingleKey _T = TypeVar('_T') +class OverlayType(Enum): + transient: str = 'transient' + main: str = 'main' + + class ParsedShortcut(NamedTuple): mods: int key_name: str @@ -160,11 +168,11 @@ def run_once(f: Callable[[], _T]) -> 'RunOnce[_T]': @run_once def modmap() -> Dict[str, int]: + from .constants import is_macos from .fast_data_types import ( GLFW_MOD_ALT, GLFW_MOD_CAPS_LOCK, GLFW_MOD_CONTROL, GLFW_MOD_HYPER, GLFW_MOD_META, GLFW_MOD_NUM_LOCK, GLFW_MOD_SHIFT, GLFW_MOD_SUPER ) - from .constants import is_macos return {'ctrl': GLFW_MOD_CONTROL, 'shift': GLFW_MOD_SHIFT, ('opt' if is_macos else 'alt'): GLFW_MOD_ALT, ('cmd' if is_macos else 'super'): GLFW_MOD_SUPER, 'hyper': GLFW_MOD_HYPER, 'meta': GLFW_MOD_META, diff --git a/kitty/window.py b/kitty/window.py index 551c30f92..544aae739 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -45,7 +45,7 @@ from .notify import NotificationCommand, handle_notification_cmd from .options.types import Options from .rgb import to_color from .terminfo import get_capabilities -from .types import MouseEvent, WindowGeometry, ac, run_once +from .types import MouseEvent, OverlayType, WindowGeometry, ac, run_once from .typing import BossType, ChildType, EdgeLiteral, TabType, TypedDict from .utils import ( docs_url, get_primary_selection, kitty_ansi_sanitizer_pat, load_shaders, @@ -462,6 +462,7 @@ global_watchers = GlobalWatchers() class Window: window_custom_type: str = '' + overlay_type = OverlayType.transient def __init__( self, @@ -642,6 +643,8 @@ class Window: } if self.window_custom_type: ans['window_custom_type'] = self.window_custom_type + if self.overlay_type is not OverlayType.transient: + ans['overlay_type'] = self.overlay_type.value return ans @property diff --git a/kitty/window_list.py b/kitty/window_list.py index db36a0a1d..0ecf16db0 100644 --- a/kitty/window_list.py +++ b/kitty/window_list.py @@ -7,7 +7,7 @@ from contextlib import suppress from itertools import count from typing import Any, Deque, Dict, Iterator, List, Optional, Tuple, Union -from .types import WindowGeometry +from .types import OverlayType, WindowGeometry from .typing import EdgeLiteral, TabType, WindowType WindowOrId = Union[WindowType, int] @@ -54,7 +54,10 @@ class WindowGroup: return False @property - def base_window_id(self) -> int: + def main_window_id(self) -> int: + for w in reversed(self.windows): + if w.overlay_type is OverlayType.main: + return w.id return self.windows[0].id if self.windows else 0 @property @@ -298,9 +301,9 @@ class WindowList: return None @property - def active_group_base(self) -> Optional[WindowType]: + def active_group_main(self) -> Optional[WindowType]: with suppress(Exception): - return self.id_map[self.groups[self.active_group_idx].base_window_id] + return self.id_map[self.groups[self.active_group_idx].main_window_id] return None def set_active_window_group_for(self, x: WindowOrId, for_keep_focus: Optional[WindowType] = None) -> None: