From 55e15dc79e3d76ef4d2043205101ba0063c10366 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 11 Aug 2020 09:25:27 +0530 Subject: [PATCH] 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 --- kittens/panel/main.py | 4 +-- kitty/boss.py | 9 ++--- kitty/config.py | 47 +------------------------- kitty/main.py | 6 ++-- kitty/os_window_size.py | 74 +++++++++++++++++++++++++++++++++++++++++ kitty/session.py | 23 ++++++------- 6 files changed, 97 insertions(+), 66 deletions(-) create mode 100644 kitty/os_window_size.py diff --git a/kittens/panel/main.py b/kittens/panel/main.py index b64e91226..15e3755fa 100644 --- a/kittens/panel/main.py +++ b/kittens/panel/main.py @@ -10,8 +10,8 @@ from typing import Callable, Dict, List, Tuple from kitty.cli import parse_args from kitty.cli_stub import PanelCLIOptions -from kitty.options_stub import Options from kitty.constants import is_macos +from kitty.os_window_size import WindowSizeData OPTIONS = r''' --lines @@ -108,7 +108,7 @@ def setup_x11_window(win_id: int) -> None: 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 def initial_window_size(cell_width: int, cell_height: int, dpi_x: float, dpi_y: float, xscale: float, yscale: float) -> Tuple[int, int]: diff --git a/kitty/boss.py b/kitty/boss.py index ae0ef2ba8..8bbbf661e 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -19,7 +19,7 @@ from .cli import create_opts, parse_args from .cli_stub import CLIOptions from .conf.utils import BadLine, to_cmdline from .config import ( - KeyAction, SubSequenceMap, common_opts_as_dict, initial_window_size_func, + KeyAction, SubSequenceMap, common_opts_as_dict, prepare_config_file_for_editing ) from .config_data import MINIMUM_FONT_SIZE @@ -40,8 +40,9 @@ from .fast_data_types import ( from .keys import get_shortcut, shortcut_matches from .layout.base import set_layout_options from .options_stub import Options +from .os_window_size import initial_window_size_func 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 ( SpecialWindow, SpecialWindowInstance, Tab, TabDict, TabManager ) @@ -195,11 +196,11 @@ class Boss: startup_id: Optional[str] = None ) -> int: 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 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( - initial_window_size_func(opts_for_size, self.cached_values), + initial_window_size_func(size_data, self.cached_values), pre_show_callback, self.args.title or appname, wname or self.args.name or wclass, wclass) tm = TabManager(os_window_id, self.opts, self.args, startup_session) diff --git a/kitty/config.py b/kitty/config.py index a2783d7bf..5a777e5c5 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -23,7 +23,7 @@ from .config_data import all_options, parse_mods, type_convert from .constants import cache_dir, defconf, is_macos from .key_names import get_key_name_lookup, key_name_aliases from .options_stub import Options as OptionsStub -from .typing import EdgeLiteral, TypedDict +from .typing import TypedDict from .utils import expandvars, log_error KeySpec = Tuple[int, bool, int] @@ -718,51 +718,6 @@ def cached_values_for(name: str) -> Generator[Dict, None, None]: 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: ans = [] for line in as_conf_file(all_options.values()): diff --git a/kitty/main.py b/kitty/main.py index 93b8640b4..a86496f8b 100644 --- a/kitty/main.py +++ b/kitty/main.py @@ -15,7 +15,7 @@ from .child import set_default_env from .cli import create_opts, parse_args from .cli_stub import CLIOptions from .conf.utils import BadLine -from .config import cached_values_for, initial_window_size_func +from .config import cached_values_for from .constants import ( appname, beam_cursor_data_file, config_dir, glfw_path, is_macos, 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.render import set_font_family 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 ( detach, expandvars, log_error, read_shell_environment, single_instance, 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 startup_notification_handler(extra_callback=run_app.first_window_callback) as pre_show_callback: 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, args.title or appname, args.name or args.cls or appname, args.cls or appname, load_all_shaders) diff --git a/kitty/os_window_size.py b/kitty/os_window_size.py new file mode 100644 index 000000000..afa10e6f5 --- /dev/null +++ b/kitty/os_window_size.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2020, Kovid Goyal + +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 diff --git a/kitty/session.py b/kitty/session.py index 7affee1a1..24af5f2fc 100644 --- a/kitty/session.py +++ b/kitty/session.py @@ -4,25 +4,24 @@ import shlex import sys -from typing import Generator, List, NamedTuple, Optional, Tuple, Union +from typing import Generator, List, Optional, Union from .cli_stub import CLIOptions 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 .options_stub import Options +from .os_window_size import WindowSize, WindowSizeData, WindowSizes from .typing import SpecialWindowInstance from .utils import log_error, resolved_shell -class WindowSizeOpts(NamedTuple): - - initial_window_width: Tuple[int, str] - initial_window_height: Tuple[int, str] - window_margin_width: FloatEdges - window_padding_width: FloatEdges - single_window_margin_width: FloatEdges - remember_window_size: bool +def get_os_window_sizing_data(opts: Options, session: Optional['Session'] = None) -> WindowSizeData: + if session is None or session.os_window_size is None: + sizes = WindowSizes(WindowSize(*opts.initial_window_width), WindowSize(*opts.initial_window_width)) + else: + sizes = session.os_window_size + return WindowSizeData(sizes, opts.remember_window_size, opts.single_window_margin_width, opts.window_margin_width, opts.window_padding_width) class Tab: @@ -43,7 +42,7 @@ class Session: self.tabs: List[Tab] = [] self.active_tab_idx = 0 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 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': from kitty.config_data import window_size 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': ans.os_window_class = rest else: