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]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 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`)

View File

@ -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 <scrollback>`,
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
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 .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 <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`
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

View File

@ -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:

View File

@ -1,16 +1,24 @@
#!/usr/bin/env python
# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
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,

View File

@ -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

View File

@ -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: