Properly type check os window initial size function

Also use the sizes specified int he session file in preference to those
specified on the command line. Fixes #2909
This commit is contained in:
Kovid Goyal 2020-08-11 09:25:27 +05:30
parent 514073cb75
commit 55e15dc79e
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 97 additions and 66 deletions

View File

@ -10,8 +10,8 @@ from typing import Callable, Dict, List, Tuple
from kitty.cli import parse_args from kitty.cli import parse_args
from kitty.cli_stub import PanelCLIOptions from kitty.cli_stub import PanelCLIOptions
from kitty.options_stub import Options
from kitty.constants import is_macos from kitty.constants import is_macos
from kitty.os_window_size import WindowSizeData
OPTIONS = r''' OPTIONS = r'''
--lines --lines
@ -108,7 +108,7 @@ def setup_x11_window(win_id: int) -> None:
func(win_id, window_width, window_height) func(win_id, window_width, window_height)
def initial_window_size_func(opts: Options, cached_values: Dict) -> Callable[[int, int, float, float, float, float], Tuple[int, int]]: def initial_window_size_func(opts: WindowSizeData, cached_values: Dict) -> Callable[[int, int, float, float, float, float], Tuple[int, int]]:
from kitty.fast_data_types import glfw_primary_monitor_size, set_smallest_allowed_resize from kitty.fast_data_types import glfw_primary_monitor_size, set_smallest_allowed_resize
def initial_window_size(cell_width: int, cell_height: int, dpi_x: float, dpi_y: float, xscale: float, yscale: float) -> Tuple[int, int]: def initial_window_size(cell_width: int, cell_height: int, dpi_x: float, dpi_y: float, xscale: float, yscale: float) -> Tuple[int, int]:

View File

@ -19,7 +19,7 @@ from .cli import create_opts, parse_args
from .cli_stub import CLIOptions from .cli_stub import CLIOptions
from .conf.utils import BadLine, to_cmdline from .conf.utils import BadLine, to_cmdline
from .config import ( from .config import (
KeyAction, SubSequenceMap, common_opts_as_dict, initial_window_size_func, KeyAction, SubSequenceMap, common_opts_as_dict,
prepare_config_file_for_editing prepare_config_file_for_editing
) )
from .config_data import MINIMUM_FONT_SIZE from .config_data import MINIMUM_FONT_SIZE
@ -40,8 +40,9 @@ from .fast_data_types import (
from .keys import get_shortcut, shortcut_matches from .keys import get_shortcut, shortcut_matches
from .layout.base import set_layout_options from .layout.base import set_layout_options
from .options_stub import Options from .options_stub import Options
from .os_window_size import initial_window_size_func
from .rgb import Color, color_from_int from .rgb import Color, color_from_int
from .session import Session, create_sessions from .session import Session, create_sessions, get_os_window_sizing_data
from .tabs import ( from .tabs import (
SpecialWindow, SpecialWindowInstance, Tab, TabDict, TabManager SpecialWindow, SpecialWindowInstance, Tab, TabDict, TabManager
) )
@ -195,11 +196,11 @@ class Boss:
startup_id: Optional[str] = None startup_id: Optional[str] = None
) -> int: ) -> int:
if os_window_id is None: if os_window_id is None:
opts_for_size = opts_for_size or getattr(startup_session, 'os_window_size', None) or self.opts size_data = get_os_window_sizing_data(opts_for_size or self.opts, startup_session)
wclass = wclass or getattr(startup_session, 'os_window_class', None) or self.args.cls or appname wclass = wclass or getattr(startup_session, 'os_window_class', None) or self.args.cls or appname
with startup_notification_handler(do_notify=startup_id is not None, startup_id=startup_id) as pre_show_callback: with startup_notification_handler(do_notify=startup_id is not None, startup_id=startup_id) as pre_show_callback:
os_window_id = create_os_window( os_window_id = create_os_window(
initial_window_size_func(opts_for_size, self.cached_values), initial_window_size_func(size_data, self.cached_values),
pre_show_callback, pre_show_callback,
self.args.title or appname, wname or self.args.name or wclass, wclass) self.args.title or appname, wname or self.args.name or wclass, wclass)
tm = TabManager(os_window_id, self.opts, self.args, startup_session) tm = TabManager(os_window_id, self.opts, self.args, startup_session)

View File

@ -23,7 +23,7 @@ from .config_data import all_options, parse_mods, type_convert
from .constants import cache_dir, defconf, is_macos from .constants import cache_dir, defconf, is_macos
from .key_names import get_key_name_lookup, key_name_aliases from .key_names import get_key_name_lookup, key_name_aliases
from .options_stub import Options as OptionsStub from .options_stub import Options as OptionsStub
from .typing import EdgeLiteral, TypedDict from .typing import TypedDict
from .utils import expandvars, log_error from .utils import expandvars, log_error
KeySpec = Tuple[int, bool, int] KeySpec = Tuple[int, bool, int]
@ -718,51 +718,6 @@ def cached_values_for(name: str) -> Generator[Dict, None, None]:
err)) err))
def initial_window_size_func(opts: OptionsStub, cached_values: Dict) -> Callable[[int, int, float, float, float, float], Tuple[int, int]]:
if 'window-size' in cached_values and opts.remember_window_size:
ws = cached_values['window-size']
try:
w, h = map(int, ws)
def initial_window_size(*a: Any) -> Tuple[int, int]:
return w, h
return initial_window_size
except Exception:
log_error('Invalid cached window size, ignoring')
w, w_unit = opts.initial_window_width
h, h_unit = opts.initial_window_height
def get_window_size(cell_width: int, cell_height: int, dpi_x: float, dpi_y: float, xscale: float, yscale: float) -> Tuple[int, int]:
if not is_macos:
# scaling is not needed on Wayland, but is needed on macOS. Not
# sure about X11.
xscale = yscale = 1
def effective_margin(which: EdgeLiteral) -> float:
ans: float = getattr(opts.single_window_margin_width, which)
if ans < 0:
ans = getattr(opts.window_margin_width, which)
return ans
if w_unit == 'cells':
spacing = effective_margin('left') + effective_margin('right')
spacing += opts.window_padding_width.left + opts.window_padding_width.right
width = cell_width * w / xscale + (dpi_x / 72) * spacing + 1
else:
width = w
if h_unit == 'cells':
spacing = effective_margin('top') + effective_margin('bottom')
spacing += opts.window_padding_width.top + opts.window_padding_width.bottom
height = cell_height * h / yscale + (dpi_y / 72) * spacing + 1
else:
height = h
return int(width), int(height)
return get_window_size
def commented_out_default_config() -> str: def commented_out_default_config() -> str:
ans = [] ans = []
for line in as_conf_file(all_options.values()): for line in as_conf_file(all_options.values()):

View File

@ -15,7 +15,7 @@ from .child import set_default_env
from .cli import create_opts, parse_args from .cli import create_opts, parse_args
from .cli_stub import CLIOptions from .cli_stub import CLIOptions
from .conf.utils import BadLine from .conf.utils import BadLine
from .config import cached_values_for, initial_window_size_func from .config import cached_values_for
from .constants import ( from .constants import (
appname, beam_cursor_data_file, config_dir, glfw_path, is_macos, appname, beam_cursor_data_file, config_dir, glfw_path, is_macos,
is_wayland, kitty_exe, logo_data_file, running_in_kitty is_wayland, kitty_exe, logo_data_file, running_in_kitty
@ -28,6 +28,8 @@ from .fast_data_types import (
from .fonts.box_drawing import set_scale from .fonts.box_drawing import set_scale
from .fonts.render import set_font_family from .fonts.render import set_font_family
from .options_stub import Options as OptionsStub from .options_stub import Options as OptionsStub
from .os_window_size import initial_window_size_func
from .session import get_os_window_sizing_data
from .utils import ( from .utils import (
detach, expandvars, log_error, read_shell_environment, single_instance, detach, expandvars, log_error, read_shell_environment, single_instance,
startup_notification_handler, unix_socket_paths startup_notification_handler, unix_socket_paths
@ -129,7 +131,7 @@ def _run_app(opts: OptionsStub, args: CLIOptions, bad_lines: Sequence[BadLine] =
with cached_values_for(run_app.cached_values_name) as cached_values: with cached_values_for(run_app.cached_values_name) as cached_values:
with startup_notification_handler(extra_callback=run_app.first_window_callback) as pre_show_callback: with startup_notification_handler(extra_callback=run_app.first_window_callback) as pre_show_callback:
window_id = create_os_window( window_id = create_os_window(
run_app.initial_window_size_func(opts, cached_values), run_app.initial_window_size_func(get_os_window_sizing_data(opts), cached_values),
pre_show_callback, pre_show_callback,
args.title or appname, args.name or args.cls or appname, args.title or appname, args.name or args.cls or appname,
args.cls or appname, load_all_shaders) args.cls or appname, load_all_shaders)

74
kitty/os_window_size.py Normal file
View File

@ -0,0 +1,74 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
from typing import Any, Callable, Dict, NamedTuple, Tuple
from .constants import FloatEdges, is_macos
from .typing import EdgeLiteral
from .utils import log_error
class WindowSize(NamedTuple):
size: int
unit: str
class WindowSizes(NamedTuple):
width: WindowSize
height: WindowSize
class WindowSizeData(NamedTuple):
initial_window_sizes: WindowSizes
remember_window_size: bool
single_window_margin_width: FloatEdges
window_margin_width: FloatEdges
window_padding_width: FloatEdges
def initial_window_size_func(opts: WindowSizeData, cached_values: Dict) -> Callable[[int, int, float, float, float, float], Tuple[int, int]]:
if 'window-size' in cached_values and opts.remember_window_size:
ws = cached_values['window-size']
try:
w, h = map(int, ws)
def initial_window_size(*a: Any) -> Tuple[int, int]:
return w, h
return initial_window_size
except Exception:
log_error('Invalid cached window size, ignoring')
w, w_unit = opts.initial_window_sizes.width
h, h_unit = opts.initial_window_sizes.height
def get_window_size(cell_width: int, cell_height: int, dpi_x: float, dpi_y: float, xscale: float, yscale: float) -> Tuple[int, int]:
if not is_macos:
# scaling is not needed on Wayland, but is needed on macOS. Not
# sure about X11.
xscale = yscale = 1
def effective_margin(which: EdgeLiteral) -> float:
ans: float = getattr(opts.single_window_margin_width, which)
if ans < 0:
ans = getattr(opts.window_margin_width, which)
return ans
if w_unit == 'cells':
spacing = effective_margin('left') + effective_margin('right')
spacing += opts.window_padding_width.left + opts.window_padding_width.right
width = cell_width * w / xscale + (dpi_x / 72) * spacing + 1
else:
width = w
if h_unit == 'cells':
spacing = effective_margin('top') + effective_margin('bottom')
spacing += opts.window_padding_width.top + opts.window_padding_width.bottom
height = cell_height * h / yscale + (dpi_y / 72) * spacing + 1
else:
height = h
return int(width), int(height)
return get_window_size

View File

@ -4,25 +4,24 @@
import shlex import shlex
import sys import sys
from typing import Generator, List, NamedTuple, Optional, Tuple, Union from typing import Generator, List, Optional, Union
from .cli_stub import CLIOptions from .cli_stub import CLIOptions
from .config_data import to_layout_names from .config_data import to_layout_names
from .constants import FloatEdges, kitty_exe from .constants import kitty_exe
from .layout.interface import all_layouts from .layout.interface import all_layouts
from .options_stub import Options from .options_stub import Options
from .os_window_size import WindowSize, WindowSizeData, WindowSizes
from .typing import SpecialWindowInstance from .typing import SpecialWindowInstance
from .utils import log_error, resolved_shell from .utils import log_error, resolved_shell
class WindowSizeOpts(NamedTuple): def get_os_window_sizing_data(opts: Options, session: Optional['Session'] = None) -> WindowSizeData:
if session is None or session.os_window_size is None:
initial_window_width: Tuple[int, str] sizes = WindowSizes(WindowSize(*opts.initial_window_width), WindowSize(*opts.initial_window_width))
initial_window_height: Tuple[int, str] else:
window_margin_width: FloatEdges sizes = session.os_window_size
window_padding_width: FloatEdges return WindowSizeData(sizes, opts.remember_window_size, opts.single_window_margin_width, opts.window_margin_width, opts.window_padding_width)
single_window_margin_width: FloatEdges
remember_window_size: bool
class Tab: class Tab:
@ -43,7 +42,7 @@ class Session:
self.tabs: List[Tab] = [] self.tabs: List[Tab] = []
self.active_tab_idx = 0 self.active_tab_idx = 0
self.default_title = default_title self.default_title = default_title
self.os_window_size: Optional[WindowSizeOpts] = None self.os_window_size: Optional[WindowSizes] = None
self.os_window_class: Optional[str] = None self.os_window_class: Optional[str] = None
def add_tab(self, opts: Options, name: str = '') -> None: def add_tab(self, opts: Options, name: str = '') -> None:
@ -125,7 +124,7 @@ def parse_session(raw: str, opts: Options, default_title: Optional[str] = None)
elif cmd == 'os_window_size': elif cmd == 'os_window_size':
from kitty.config_data import window_size from kitty.config_data import window_size
w, h = map(window_size, rest.split(maxsplit=1)) w, h = map(window_size, rest.split(maxsplit=1))
ans.os_window_size = WindowSizeOpts(w, h, opts.window_margin_width, opts.window_padding_width, opts.single_window_margin_width, False) ans.os_window_size = WindowSizes(WindowSize(*w), WindowSize(*h))
elif cmd == 'os_window_class': elif cmd == 'os_window_class':
ans.os_window_class = rest ans.os_window_class = rest
else: else: