Allow creating overlay-main windows, which are treated as the active window unlike normal overlays

Fixes #5392
This commit is contained in:
Kovid Goyal 2022-09-03 19:04:31 +05:30
parent a420d9d19c
commit 607bc845fc
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
7 changed files with 42 additions and 12 deletions

View File

@ -38,6 +38,8 @@ Detailed list of changes
0.26.2 [future] 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`) - 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`) - 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`)

View File

@ -32,7 +32,12 @@ Glossary
top of an existing kitty window, entirely covering it. Overlays are used top of an existing kitty window, entirely covering it. Overlays are used
throughout kitty, for example, to display the :ref:`the scrollback buffer <scrollback>`, throughout kitty, for example, to display the :ref:`the scrollback buffer <scrollback>`,
to display :doc:`hints </kittens/hints>`, for :doc:`unicode input to display :doc:`hints </kittens/hints>`, for :doc:`unicode input
</kittens/unicode_input>` etc. </kittens/unicode_input>` 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 hyperlinks
Terminals can have hyperlinks, just like the internet. In kitty you can Terminals can have hyperlinks, just like the internet. In kitty you can

View File

@ -21,7 +21,7 @@ from .fast_data_types import (
) )
from .options.utils import env as parse_env from .options.utils import env as parse_env
from .tabs import Tab, TabManager from .tabs import Tab, TabManager
from .types import run_once from .types import OverlayType, run_once
from .utils import ( from .utils import (
get_editor, log_error, resolve_custom_file, set_primary_selection, which 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
type=choices type=choices
default=window 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: Where to launch the child process:
:code:`window` :code:`window`
@ -71,6 +71,13 @@ Where to launch the child process:
:code:`overlay` :code:`overlay`
An :term:`overlay window <overlay>` covering the current active kitty window An :term:`overlay window <overlay>` covering the current active kitty window
:code:`overlay-main`
An :term:`overlay window <overlay>` 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` :code:`background`
The process will be run in the :italic:`background`, without a kitty window. The process will be run in the :italic:`background`, without a kitty window.
@ -539,7 +546,7 @@ def launch(
kw['cmd'] = final_cmd kw['cmd'] = final_cmd
if force_window_launch and opts.type not in non_window_launch_types: if force_window_launch and opts.type not in non_window_launch_types:
opts.type = 'window' opts.type = 'window'
if opts.type == 'overlay' and active: if opts.type in ('overlay', 'overlay-main') and active:
kw['overlay_for'] = active.id kw['overlay_for'] = active.id
if opts.type == 'background': if opts.type == 'background':
cmd = kw['cmd'] cmd = kw['cmd']
@ -573,6 +580,8 @@ def launch(
boss.set_active_window(active, switch_os_window_if_needed=True, for_keep_focus=True) boss.set_active_window(active, switch_os_window_if_needed=True, for_keep_focus=True)
if opts.logo: if opts.logo:
new_window.set_logo(opts.logo, opts.logo_position or '', opts.logo_alpha) 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 new_window
return None return None

View File

@ -211,7 +211,7 @@ class Tab: # {{{
@property @property
def active_window_for_cwd(self) -> Optional[Window]: def active_window_for_cwd(self) -> Optional[Window]:
return self.windows.active_group_base return self.windows.active_group_main
@property @property
def title(self) -> str: def title(self) -> str:

View File

@ -1,16 +1,24 @@
#!/usr/bin/env python #!/usr/bin/env python
# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net> # License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
from enum import Enum
from functools import update_wrapper from functools import update_wrapper
from typing import ( 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: if TYPE_CHECKING:
from kitty.fast_data_types import SingleKey from kitty.fast_data_types import SingleKey
_T = TypeVar('_T') _T = TypeVar('_T')
class OverlayType(Enum):
transient: str = 'transient'
main: str = 'main'
class ParsedShortcut(NamedTuple): class ParsedShortcut(NamedTuple):
mods: int mods: int
key_name: str key_name: str
@ -160,11 +168,11 @@ def run_once(f: Callable[[], _T]) -> 'RunOnce[_T]':
@run_once @run_once
def modmap() -> Dict[str, int]: def modmap() -> Dict[str, int]:
from .constants import is_macos
from .fast_data_types import ( from .fast_data_types import (
GLFW_MOD_ALT, GLFW_MOD_CAPS_LOCK, GLFW_MOD_CONTROL, GLFW_MOD_HYPER, 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 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, 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, ('cmd' if is_macos else 'super'): GLFW_MOD_SUPER, 'hyper': GLFW_MOD_HYPER, 'meta': GLFW_MOD_META,

View File

@ -45,7 +45,7 @@ from .notify import NotificationCommand, handle_notification_cmd
from .options.types import Options from .options.types import Options
from .rgb import to_color from .rgb import to_color
from .terminfo import get_capabilities 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 .typing import BossType, ChildType, EdgeLiteral, TabType, TypedDict
from .utils import ( from .utils import (
docs_url, get_primary_selection, kitty_ansi_sanitizer_pat, load_shaders, docs_url, get_primary_selection, kitty_ansi_sanitizer_pat, load_shaders,
@ -462,6 +462,7 @@ global_watchers = GlobalWatchers()
class Window: class Window:
window_custom_type: str = '' window_custom_type: str = ''
overlay_type = OverlayType.transient
def __init__( def __init__(
self, self,
@ -642,6 +643,8 @@ class Window:
} }
if self.window_custom_type: if self.window_custom_type:
ans['window_custom_type'] = 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 return ans
@property @property

View File

@ -7,7 +7,7 @@ from contextlib import suppress
from itertools import count from itertools import count
from typing import Any, Deque, Dict, Iterator, List, Optional, Tuple, Union 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 from .typing import EdgeLiteral, TabType, WindowType
WindowOrId = Union[WindowType, int] WindowOrId = Union[WindowType, int]
@ -54,7 +54,10 @@ class WindowGroup:
return False return False
@property @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 return self.windows[0].id if self.windows else 0
@property @property
@ -298,9 +301,9 @@ class WindowList:
return None return None
@property @property
def active_group_base(self) -> Optional[WindowType]: def active_group_main(self) -> Optional[WindowType]:
with suppress(Exception): 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 return None
def set_active_window_group_for(self, x: WindowOrId, for_keep_focus: Optional[WindowType] = None) -> None: def set_active_window_group_for(self, x: WindowOrId, for_keep_focus: Optional[WindowType] = None) -> None: