Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b0724530e | ||
|
|
e5681a93f9 | ||
|
|
fb838a694e | ||
|
|
8c6f188767 | ||
|
|
55e15dc79e | ||
|
|
514073cb75 | ||
|
|
f6ece6522e | ||
|
|
817f0997cf | ||
|
|
1d651270d3 | ||
|
|
6ea58fac1a | ||
|
|
c7eb63d4ff | ||
|
|
4062365b19 | ||
|
|
7f48a927de | ||
|
|
4a740cc556 | ||
|
|
628b92f20b | ||
|
|
8f9616c230 | ||
|
|
df475dfde5 | ||
|
|
a835b56a51 | ||
|
|
5555a66638 | ||
|
|
dad355b932 | ||
|
|
90a097d45c | ||
|
|
dba01bc014 | ||
|
|
1d0a3ce998 | ||
|
|
076ad850bb | ||
|
|
868546abe4 | ||
|
|
6b421fabd1 | ||
|
|
ab3c9658bd | ||
|
|
8c7886d429 | ||
|
|
110a3e7e0f | ||
|
|
ee0b70f51b | ||
|
|
df48061a8f | ||
|
|
b1387d50f0 | ||
|
|
73dd218a95 | ||
|
|
ee4cedcc81 | ||
|
|
d1b2f9c6a9 | ||
|
|
40dee44978 | ||
|
|
db04c70d4a | ||
|
|
7401c6ac97 | ||
|
|
f7a1222cc3 | ||
|
|
069f09c43c | ||
|
|
35f821f6a1 | ||
|
|
67f60847ee | ||
|
|
65f6b142a5 |
@@ -7,6 +7,7 @@ import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from contextlib import suppress
|
||||
|
||||
from bypy.constants import (
|
||||
LIBDIR, PREFIX, PYTHON, SRC as KITTY_DIR, ismacos, worker_env
|
||||
@@ -47,6 +48,16 @@ def build_c_extensions(ext_dir, args):
|
||||
shutil.copytree(
|
||||
KITTY_DIR, writeable_src_dir, symlinks=True,
|
||||
ignore=shutil.ignore_patterns('b', 'build', 'dist', '*_commands.json', '*.o'))
|
||||
|
||||
# Build the launcher as it is needed for the spawn test
|
||||
with suppress(FileNotFoundError):
|
||||
os.remove(os.path.join(writeable_src_dir, 'kitty', 'launcher', 'kitty'))
|
||||
if run(PYTHON, 'setup.py', 'build-launcher', cwd=writeable_src_dir) != 0:
|
||||
print('Building of kitty launcher failed', file=sys.stderr)
|
||||
os.chdir(KITTY_DIR)
|
||||
run_shell()
|
||||
raise SystemExit('Building of kitty launcher failed')
|
||||
|
||||
cmd = [PYTHON, 'setup.py']
|
||||
bundle = 'macos-freeze' if ismacos else 'linux-freeze'
|
||||
cmd.append(bundle)
|
||||
|
||||
@@ -4,6 +4,27 @@ Changelog
|
||||
|kitty| is a feature full, cross-platform, *fast*, GPU based terminal emulator.
|
||||
To update |kitty|, :doc:`follow the instructions <binary>`.
|
||||
|
||||
0.18.3 [2020-08-11]
|
||||
-------------------
|
||||
|
||||
- hints kitten: Allow customizing hint colors (:pull:`2894`)
|
||||
|
||||
- Wayland: Fix a typo in the previous release that broke reading mouse cursor size (:iss:`2895`)
|
||||
|
||||
- Fix a regression in the previous release that could cause an exception during
|
||||
startup in rare circumstances (:iss:`2896`)
|
||||
|
||||
- Fix image leaving behind a black rectangle when switch away and back to
|
||||
alternate screen (:iss:`2901`)
|
||||
|
||||
- Fix one pixel mis-alignment of rounded corners when either the cell
|
||||
dimensions or the thickness of the line is an odd number of pixels
|
||||
(:iss:`2907`)
|
||||
|
||||
- Fix a regression that broke specifying OS window size in the session file
|
||||
(:iss:`2908`)
|
||||
|
||||
|
||||
0.18.2 [2020-07-28]
|
||||
--------------------
|
||||
|
||||
@@ -25,7 +46,7 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
|
||||
- When a character from the Unicode Dingbat block is followed by a space, use
|
||||
the extra space to render a larger version of the character (:iss:`2850`)
|
||||
|
||||
- macOS: Fix the LC_TYPE env var being set to UTF-8 on systems in which the
|
||||
- macOS: Fix the LC_CTYPE env var being set to UTF-8 on systems in which the
|
||||
language and country code do not form a valid locale (:iss:`1233`)
|
||||
|
||||
- macOS: Fix :kbd:`cmd+plus` not changing font size (:iss:`2839`)
|
||||
|
||||
@@ -24,6 +24,9 @@ images and other types of documents directly in your terminal, even over SSH.
|
||||
`nnn <https://github.com/jarun/nnn/>`_
|
||||
another terminal file manager, with previews of file contents powered by kitty's graphics protocol.
|
||||
|
||||
`hunter <https://github.com/rabite0/hunter>`_
|
||||
another terminal file manager, with previews of file contents powered by kitty's graphics protocol.
|
||||
|
||||
`koneko <https://github.com/twenty5151/koneko>`_
|
||||
browse images from the pixiv artist community directly in kitty
|
||||
|
||||
@@ -109,3 +112,7 @@ Miscellaneous
|
||||
|
||||
`kitti3 <https://github.com/LandingEllipse/kitti3>`_
|
||||
allow using kitty as a drop-down terminal under the i3 window manager
|
||||
|
||||
`weechat-hints <https://github.com/GermainZ/kitty-weechat-hints>`_
|
||||
URL hints kitten for WeeChat that works without having to use WeeChat's
|
||||
raw-mode.
|
||||
|
||||
@@ -196,3 +196,7 @@ Kittens created by kitty users
|
||||
`insert password <https://github.com/kovidgoyal/kitty/issues/1222>`_
|
||||
Insert a password from a CLI password manager, taking care to only do it at
|
||||
a password prompt.
|
||||
|
||||
`weechat-hints <https://github.com/GermainZ/kitty-weechat-hints>`_
|
||||
URL hints kitten for WeeChat that works without having to use WeeChat's
|
||||
raw-mode.
|
||||
|
||||
@@ -10,18 +10,18 @@ form::
|
||||
Where ``<ESC>`` is the byte ``0x1b``. The JSON object has the form::
|
||||
|
||||
{
|
||||
'cmd': "command name",
|
||||
'version': "kitty version",
|
||||
'no_response': Optional Boolean,
|
||||
'payload': <Optional JSON object>,
|
||||
"cmd": "command name",
|
||||
"version": <kitty version>,
|
||||
"no_response": Optional Boolean,
|
||||
"payload": <Optional JSON object>,
|
||||
}
|
||||
|
||||
The ``version`` above is a string of the form :code:`0.14.2`. If you are developing a
|
||||
The ``version`` above is an array of the form :code:`[0, 14, 2]`. If you are developing a
|
||||
standalone client, use the kitty version that you are developing against. Using
|
||||
a version greater than the version of the kitty instance you are talking to,
|
||||
will cause a failure.
|
||||
|
||||
Set ``no_response`` to True if you don't want a response from kitty.
|
||||
Set ``no_response`` to ``true`` if you don't want a response from kitty.
|
||||
|
||||
The optional payload is a JSON object that is specific to the actual command being sent.
|
||||
The fields in the object for every command are documented below.
|
||||
|
||||
@@ -274,7 +274,9 @@ def category_test(
|
||||
comment: str,
|
||||
use_static: bool = False,
|
||||
extra_chars: Union[FrozenSet[int], Set[int]] = frozenset(),
|
||||
exclude: Union[Set[int], FrozenSet[int]] = frozenset()
|
||||
exclude: Union[Set[int], FrozenSet[int]] = frozenset(),
|
||||
least_check_return: Optional[str] = None,
|
||||
ascii_range: Optional[str] = None
|
||||
) -> None:
|
||||
static = 'static inline ' if use_static else ''
|
||||
chars: Set[int] = set()
|
||||
@@ -284,6 +286,11 @@ def category_test(
|
||||
chars -= exclude
|
||||
p(f'{static}bool\n{name}(char_type code) {{')
|
||||
p(f'\t// {comment} ({len(chars)} codepoints)' + ' {{' '{')
|
||||
if least_check_return is not None:
|
||||
least = min(chars)
|
||||
p(f'\tif (LIKELY(code < {least})) return {least_check_return};')
|
||||
if ascii_range is not None:
|
||||
p(f'\tif (LIKELY(0x20 <= code && code <= 0x7e)) return {ascii_range};')
|
||||
p('\tswitch(code) {')
|
||||
for spec in get_ranges(list(chars)):
|
||||
write_case(spec, p)
|
||||
@@ -337,11 +344,15 @@ def gen_ucd() -> None:
|
||||
{c for c in class_maps if c.startswith('M')},
|
||||
'M category (marks)',
|
||||
# See https://github.com/harfbuzz/harfbuzz/issues/169
|
||||
extra_chars=emoji_skin_tone_modifiers | {zwj}
|
||||
extra_chars=emoji_skin_tone_modifiers | {zwj},
|
||||
least_check_return='false'
|
||||
)
|
||||
category_test(
|
||||
'is_ignored_char', p, 'Cc Cf Cs'.split(),
|
||||
'Control characters and non-characters', extra_chars=non_characters, exclude={zwj})
|
||||
'Control characters and non-characters',
|
||||
extra_chars=non_characters, exclude={zwj},
|
||||
ascii_range='false'
|
||||
)
|
||||
category_test('is_word_char', p, {c for c in class_maps if c[0] in 'LN'}, 'L and N categories')
|
||||
category_test('is_CZ_category', p, cz, 'C and Z categories')
|
||||
category_test('is_P_category', p, {c for c in class_maps if c[0] == 'P'}, 'P category (punctuation)')
|
||||
@@ -421,7 +432,7 @@ def gen_names() -> None:
|
||||
p('}; // }}}\n')
|
||||
|
||||
# The trie
|
||||
p('typedef struct {{ uint32_t children_offset; uint32_t match_offset; }} word_trie;\n')
|
||||
p('typedef struct { uint32_t children_offset; uint32_t match_offset; } word_trie;\n')
|
||||
all_trie_nodes: List['TrieNode'] = [] # noqa
|
||||
|
||||
class TrieNode:
|
||||
@@ -482,6 +493,7 @@ def gen_wcwidth() -> None:
|
||||
|
||||
with create_header('kitty/wcwidth-std.h') as p:
|
||||
p('static int\nwcwidth_std(int32_t code) {')
|
||||
p('\tif (LIKELY(0x20 <= code && code <= 0x7e)) return 1;')
|
||||
p('\tswitch(code) {')
|
||||
|
||||
non_printing = class_maps['Cc'] | class_maps['Cf'] | class_maps['Cs']
|
||||
|
||||
2
glfw/ibus_glfw.c
vendored
2
glfw/ibus_glfw.c
vendored
@@ -269,7 +269,7 @@ setup_connection(_GLFWIBUSData *ibus) {
|
||||
ibus->conn = NULL;
|
||||
}
|
||||
debug("Connecting to IBUS daemon @ %s for IME input management\n", ibus->address);
|
||||
ibus->conn = glfw_dbus_connect_to(ibus->address, "Failed to connect to the IBUS daemon, with error", "ibus", false);
|
||||
ibus->conn = glfw_dbus_connect_to(ibus->address, "Failed to connect to the IBUS daemon, with error", "ibus", true);
|
||||
if (!ibus->conn) return false;
|
||||
free((void*)ibus->input_ctx_path); ibus->input_ctx_path = NULL;
|
||||
if (!glfw_dbus_call_method_with_reply(
|
||||
|
||||
2
glfw/null_joystick.c
vendored
2
glfw/null_joystick.c
vendored
@@ -33,7 +33,7 @@
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformInitJoysticks(void)
|
||||
bool _glfwPlatformInitJoysticks(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
2
glfw/wl_cursors.c
vendored
2
glfw/wl_cursors.c
vendored
@@ -16,7 +16,7 @@ pixels_from_scale(int scale) {
|
||||
const char *env = getenv("XCURSOR_SIZE");
|
||||
if (env) {
|
||||
const int retval = atoi(env);
|
||||
if (retval > 0 && retval < 2048) factor = 32;
|
||||
if (retval > 0 && retval < 2048) factor = retval;
|
||||
}
|
||||
queried_env = true;
|
||||
}
|
||||
|
||||
2
glfw/wl_init.c
vendored
2
glfw/wl_init.c
vendored
@@ -802,6 +802,7 @@ void _glfwPlatformTerminate(void)
|
||||
glfw_xkb_release(&_glfw.wl.xkb);
|
||||
glfw_dbus_terminate(&_glfw.wl.dbus);
|
||||
|
||||
glfw_wlc_destroy();
|
||||
if (_glfw.wl.cursor.handle)
|
||||
{
|
||||
_glfw_dlclose(_glfw.wl.cursor.handle);
|
||||
@@ -810,7 +811,6 @@ void _glfwPlatformTerminate(void)
|
||||
|
||||
if (_glfw.wl.cursorSurface)
|
||||
wl_surface_destroy(_glfw.wl.cursorSurface);
|
||||
glfw_wlc_destroy();
|
||||
if (_glfw.wl.subcompositor)
|
||||
wl_subcompositor_destroy(_glfw.wl.subcompositor);
|
||||
if (_glfw.wl.compositor)
|
||||
|
||||
@@ -72,7 +72,7 @@ def decode_hint(x: str, alphabet: str = DEFAULT_HINT_ALPHABET) -> int:
|
||||
return i
|
||||
|
||||
|
||||
def highlight_mark(m: Mark, text: str, current_input: str, alphabet: str) -> str:
|
||||
def highlight_mark(m: Mark, text: str, current_input: str, alphabet: str, colors: Dict[str, str]) -> str:
|
||||
hint = encode_hint(m.index, alphabet)
|
||||
if current_input and not hint.startswith(current_input):
|
||||
return faint(text)
|
||||
@@ -80,19 +80,19 @@ def highlight_mark(m: Mark, text: str, current_input: str, alphabet: str) -> str
|
||||
text = text[len(hint):]
|
||||
return styled(
|
||||
hint,
|
||||
fg='black',
|
||||
bg='green',
|
||||
fg=colors['foreground'],
|
||||
bg=colors['background'],
|
||||
bold=True
|
||||
) + styled(
|
||||
text, fg='gray', fg_intense=True, bold=True
|
||||
text, fg=colors['text'], fg_intense=True, bold=True
|
||||
)
|
||||
|
||||
|
||||
def render(text: str, current_input: str, all_marks: Sequence[Mark], ignore_mark_indices: Set[int], alphabet: str) -> str:
|
||||
def render(text: str, current_input: str, all_marks: Sequence[Mark], ignore_mark_indices: Set[int], alphabet: str, colors: Dict[str, str]) -> str:
|
||||
for mark in reversed(all_marks):
|
||||
if mark.index in ignore_mark_indices:
|
||||
continue
|
||||
mtext = highlight_mark(mark, text[mark.start:mark.end], current_input, alphabet)
|
||||
mtext = highlight_mark(mark, text[mark.start:mark.end], current_input, alphabet, colors)
|
||||
text = text[:mark.start] + mtext + text[mark.end:]
|
||||
|
||||
text = text.replace('\0', '')
|
||||
@@ -105,6 +105,9 @@ class Hints(Handler):
|
||||
def __init__(self, text: str, all_marks: Sequence[Mark], index_map: Dict[int, Mark], args: HintsCLIOptions):
|
||||
self.text, self.index_map = text, index_map
|
||||
self.alphabet = args.alphabet or DEFAULT_HINT_ALPHABET
|
||||
self.colors = {'foreground': args.hints_foreground_color,
|
||||
'background': args.hints_background_color,
|
||||
'text': args.hints_text_color}
|
||||
self.all_marks = all_marks
|
||||
self.ignore_mark_indices: Set[int] = set()
|
||||
self.args = args
|
||||
@@ -198,7 +201,7 @@ class Hints(Handler):
|
||||
|
||||
def draw_screen(self) -> None:
|
||||
if self.current_text is None:
|
||||
self.current_text = render(self.text, self.current_input, self.all_marks, self.ignore_mark_indices, self.alphabet)
|
||||
self.current_text = render(self.text, self.current_input, self.all_marks, self.ignore_mark_indices, self.alphabet, self.colors)
|
||||
self.cmd.clear_screen()
|
||||
self.write(self.current_text)
|
||||
|
||||
@@ -513,6 +516,24 @@ type=bool-set
|
||||
Have the hints increase from top to bottom instead of decreasing from top to bottom.
|
||||
|
||||
|
||||
--hints-foreground-color
|
||||
default=black
|
||||
type=str
|
||||
The foreground color for hints
|
||||
|
||||
|
||||
--hints-background-color
|
||||
default=green
|
||||
type=str
|
||||
The background color for hints
|
||||
|
||||
|
||||
--hints-text-color
|
||||
default=gray
|
||||
type=str
|
||||
The foreground color for text pointed to by the hints
|
||||
|
||||
|
||||
--customize-processing
|
||||
Name of a python file in the kitty config directory which will be imported to provide
|
||||
custom implementations for pattern finding and performing actions
|
||||
|
||||
@@ -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]:
|
||||
|
||||
2
kittens/unicode_input/names.h
generated
2
kittens/unicode_input/names.h
generated
@@ -1,4 +1,4 @@
|
||||
// unicode data, built from the unicode standard on: 2020-04-06
|
||||
// unicode data, built from the unicode standard on: 2020-08-06
|
||||
// see gen-wcwidth.py
|
||||
#pragma once
|
||||
#include "data-types.h"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -537,6 +537,11 @@ cocoa_hide_titlebar(void *w)
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
void
|
||||
cocoa_system_beep(void) {
|
||||
NSBeep();
|
||||
}
|
||||
|
||||
static PyMethodDef module_methods[] = {
|
||||
{"cocoa_get_lang", (PyCFunction)cocoa_get_lang, METH_NOARGS, ""},
|
||||
{"cocoa_set_new_window_trigger", (PyCFunction)cocoa_set_new_window_trigger, METH_VARARGS, ""},
|
||||
|
||||
@@ -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()):
|
||||
|
||||
@@ -20,7 +20,7 @@ class Version(NamedTuple):
|
||||
|
||||
|
||||
appname: str = 'kitty'
|
||||
version: Version = Version(0, 18, 2)
|
||||
version: Version = Version(0, 18, 3)
|
||||
str_version: str = '.'.join(map(str, version))
|
||||
_plat = sys.platform.lower()
|
||||
is_macos: bool = 'darwin' in _plat
|
||||
@@ -64,16 +64,16 @@ class WindowGeometry(NamedTuple):
|
||||
def kitty_exe() -> str:
|
||||
rpath = sys._xoptions.get('bundle_exe_dir')
|
||||
if not rpath:
|
||||
items = filter(None, os.environ.get('PATH', '').split(os.pathsep))
|
||||
items = os.environ.get('PATH', '').split(os.pathsep) + [os.path.join(base, 'launcher')]
|
||||
seen: Set[str] = set()
|
||||
for candidate in items:
|
||||
for candidate in filter(None, items):
|
||||
if candidate not in seen:
|
||||
seen.add(candidate)
|
||||
if os.access(os.path.join(candidate, 'kitty'), os.X_OK):
|
||||
rpath = candidate
|
||||
break
|
||||
else:
|
||||
rpath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'launcher')
|
||||
raise RuntimeError('kitty binary not found')
|
||||
return os.path.join(rpath, 'kitty')
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ def wakeup() -> None:
|
||||
b.child_monitor.wakeup()
|
||||
|
||||
|
||||
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
base_dir = os.path.dirname(base)
|
||||
terminfo_dir = os.path.join(base_dir, 'terminfo')
|
||||
logo_data_file = os.path.join(base_dir, 'logo', 'kitty.rgba')
|
||||
logo_png_file = os.path.join(base_dir, 'logo', 'kitty.png')
|
||||
|
||||
2
kitty/emoji.h
generated
2
kitty/emoji.h
generated
@@ -1,4 +1,4 @@
|
||||
// unicode data, built from the unicode standard on: 2020-04-06
|
||||
// unicode data, built from the unicode standard on: 2020-08-06
|
||||
// see gen-wcwidth.py
|
||||
#pragma once
|
||||
#include "data-types.h"
|
||||
|
||||
@@ -364,20 +364,19 @@ def D(buf: BufType, width: int, height: int, left: bool = True) -> None:
|
||||
buf[offset + dest_x] = mbuf[offset + src_x]
|
||||
|
||||
|
||||
def draw_parametrized_curve(buf: BufType, width: int, height: int, thickness_in_pixels: int, xfunc: BezierFunc, yfunc: BezierFunc) -> None:
|
||||
def draw_parametrized_curve(buf: BufType, width: int, height: int, delta: int, extra: int, xfunc: BezierFunc, yfunc: BezierFunc) -> None:
|
||||
num_samples = height*4
|
||||
seen = set()
|
||||
delta, extra = divmod(thickness_in_pixels, 2)
|
||||
for i in range(num_samples + 1):
|
||||
t = (i / num_samples)
|
||||
p = x_p, y_p = int(xfunc(t)), int(yfunc(t))
|
||||
if p in seen:
|
||||
continue
|
||||
seen.add(p)
|
||||
for y in range(int(y_p) - delta, int(y_p) + delta + extra):
|
||||
for y in range(y_p - delta, y_p + delta + extra):
|
||||
if 0 <= y < height:
|
||||
offset = y * width
|
||||
for x in range(int(x_p) - delta, int(x_p) + delta + extra):
|
||||
for x in range(x_p - delta, x_p + delta + extra):
|
||||
if 0 <= x < width:
|
||||
pos = offset + x
|
||||
buf[pos] = min(255, buf[pos] + 255)
|
||||
@@ -386,29 +385,31 @@ def draw_parametrized_curve(buf: BufType, width: int, height: int, thickness_in_
|
||||
@supersampled()
|
||||
def rounded_corner(buf: BufType, width: int, height: int, level: int = 1, which: str = '╭') -> None:
|
||||
supersample_factor = getattr(buf, 'supersample_factor')
|
||||
thickness_in_pixels = thickness(level) * supersample_factor
|
||||
delta, extra = divmod(thickness(level), 2)
|
||||
hw = ((width / supersample_factor) // 2) * supersample_factor
|
||||
hh = ((height / supersample_factor) // 2) * supersample_factor
|
||||
if which == '╭':
|
||||
start = width // 2, height - 1
|
||||
end = width - 1, height // 2
|
||||
c1 = width // 2, int(0.75 * height)
|
||||
c2 = width // 2, height // 2 + 1
|
||||
start = hw, height - 1
|
||||
end = width - 1, hh
|
||||
c1 = hw, int(0.75 * height)
|
||||
c2 = hw, hh + 1
|
||||
elif which == '╮':
|
||||
start = 0, height // 2
|
||||
end = width // 2, height - 1
|
||||
c1 = width // 2, height // 2 + 1
|
||||
c2 = width // 2, int(0.75 * height)
|
||||
start = 0, hh
|
||||
end = hw, height - 1
|
||||
c1 = hw, hh + 1
|
||||
c2 = hw, int(0.75 * height)
|
||||
elif which == '╰':
|
||||
start = width // 2, 0
|
||||
end = width - 1, height // 2
|
||||
c1 = width // 2, int(0.25 * height)
|
||||
c2 = width // 2 - 1, height // 2 - 1
|
||||
end = width - 1, hh
|
||||
c1 = hw, int(0.25 * height)
|
||||
c2 = hw, hh - 1
|
||||
elif which == '╯':
|
||||
start = 0, height // 2
|
||||
end = width // 2, 0
|
||||
c1 = width // 2 - 1, height // 2 - 1
|
||||
c2 = width // 2, int(0.25 * height)
|
||||
start = 0, hh
|
||||
end = hw, 0
|
||||
c1 = hw, hh - 1
|
||||
c2 = hw, int(0.25 * height)
|
||||
xfunc, yfunc = cubic_bezier(start, end, c1, c2)
|
||||
draw_parametrized_curve(buf, width, height, thickness_in_pixels, xfunc, yfunc)
|
||||
draw_parametrized_curve(buf, width, height, delta * supersample_factor, extra * supersample_factor, xfunc, yfunc)
|
||||
|
||||
|
||||
def half_dhline(buf: BufType, width: int, height: int, level: int = 1, which: str = 'left', only: Optional[str] = None) -> Tuple[int, int]:
|
||||
@@ -686,7 +687,7 @@ t, f = 1, 3
|
||||
for start in '┌┐└┘':
|
||||
for i, (hlevel, vlevel) in enumerate(((t, t), (f, t), (t, f), (f, f))):
|
||||
box_chars[chr(ord(start) + i)] = [p(corner, which=start, hlevel=hlevel, vlevel=vlevel)]
|
||||
for ch in '╭╮╯╰':
|
||||
for ch in '╭╮╰╯':
|
||||
box_chars[ch] = [p(rounded_corner, which=ch)]
|
||||
|
||||
for i, (a_, b_, c_, d_) in enumerate((
|
||||
|
||||
16
kitty/glfw.c
16
kitty/glfw.c
@@ -15,6 +15,7 @@ extern long cocoa_window_number(void *w);
|
||||
extern void cocoa_create_global_menu(void);
|
||||
extern void cocoa_hide_window_title(void *w);
|
||||
extern void cocoa_hide_titlebar(void *w);
|
||||
extern void cocoa_system_beep(void);
|
||||
extern void cocoa_set_activation_policy(bool);
|
||||
extern void cocoa_set_titlebar_color(void *w, color_type color);
|
||||
extern bool cocoa_alt_option_key_pressed(unsigned long);
|
||||
@@ -888,16 +889,14 @@ get_clipboard_string(PYNOARG) {
|
||||
return Py_BuildValue("s", "");
|
||||
}
|
||||
|
||||
void
|
||||
ring_audio_bell(OSWindow *w UNUSED) {
|
||||
static void
|
||||
ring_audio_bell(void) {
|
||||
static monotonic_t last_bell_at = -1;
|
||||
monotonic_t now = monotonic();
|
||||
if (now - last_bell_at <= ms_to_monotonic_t(100ll)) return;
|
||||
if (last_bell_at >= 0 && now - last_bell_at <= ms_to_monotonic_t(100ll)) return;
|
||||
last_bell_at = now;
|
||||
#ifdef __APPLE__
|
||||
if (w->handle) {
|
||||
glfwWindowBell(w->handle);
|
||||
}
|
||||
cocoa_system_beep();
|
||||
#else
|
||||
play_canberra_sound("bell", "kitty bell");
|
||||
#endif
|
||||
@@ -905,8 +904,7 @@ ring_audio_bell(OSWindow *w UNUSED) {
|
||||
|
||||
static PyObject*
|
||||
ring_bell(PYNOARG) {
|
||||
OSWindow *w = current_os_window();
|
||||
ring_audio_bell(w);
|
||||
ring_audio_bell();
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
@@ -960,7 +958,7 @@ void
|
||||
request_window_attention(id_type kitty_window_id, bool audio_bell) {
|
||||
OSWindow *w = os_window_for_kitty_window(kitty_window_id);
|
||||
if (w) {
|
||||
if (audio_bell) ring_audio_bell(w);
|
||||
if (audio_bell) ring_audio_bell();
|
||||
if (OPT(window_alert_on_bell)) glfwRequestWindowAttention(w->handle);
|
||||
glfwPostEmptyEvent();
|
||||
}
|
||||
|
||||
@@ -645,20 +645,32 @@ grman_update_layers(GraphicsManager *self, unsigned int scrolled_by, float scree
|
||||
// Image lifetime/scrolling {{{
|
||||
|
||||
static inline void
|
||||
filter_refs(GraphicsManager *self, const void* data, bool free_images, bool (*filter_func)(ImageRef*, Image*, const void*, CellPixelSize), CellPixelSize cell) {
|
||||
self->layers_dirty = self->image_count > 0;
|
||||
filter_refs(GraphicsManager *self, const void* data, bool free_images, bool (*filter_func)(const ImageRef*, Image*, const void*, CellPixelSize), CellPixelSize cell) {
|
||||
for (size_t i = self->image_count; i-- > 0;) {
|
||||
Image *img = self->images + i;
|
||||
for (size_t j = img->refcnt; j-- > 0;) {
|
||||
ImageRef *ref = img->refs + j;
|
||||
if (filter_func(ref, img, data, cell)) {
|
||||
remove_i_from_array(img->refs, j, img->refcnt);
|
||||
self->layers_dirty = true;
|
||||
}
|
||||
}
|
||||
if (img->refcnt == 0 && (free_images || img->client_id == 0)) remove_image(self, i);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
modify_refs(GraphicsManager *self, const void* data, bool free_images, bool (*filter_func)(ImageRef*, Image*, const void*, CellPixelSize), CellPixelSize cell) {
|
||||
for (size_t i = self->image_count; i-- > 0;) {
|
||||
Image *img = self->images + i;
|
||||
for (size_t j = img->refcnt; j-- > 0;) {
|
||||
if (filter_func(img->refs + j, img, data, cell)) remove_i_from_array(img->refs, j, img->refcnt);
|
||||
}
|
||||
if (img->refcnt == 0 && (free_images || img->client_id == 0)) remove_image(self, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
scroll_filter_func(ImageRef *ref, Image UNUSED *img, const void *data, CellPixelSize cell UNUSED) {
|
||||
ScrollData *d = (ScrollData*)data;
|
||||
@@ -667,12 +679,12 @@ scroll_filter_func(ImageRef *ref, Image UNUSED *img, const void *data, CellPixel
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ref_within_region(ImageRef *ref, index_type margin_top, index_type margin_bottom) {
|
||||
ref_within_region(const ImageRef *ref, index_type margin_top, index_type margin_bottom) {
|
||||
return ref->start_row >= (int32_t)margin_top && ref->start_row + ref->effective_num_rows <= margin_bottom;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ref_outside_region(ImageRef *ref, index_type margin_top, index_type margin_bottom) {
|
||||
ref_outside_region(const ImageRef *ref, index_type margin_top, index_type margin_bottom) {
|
||||
return ref->start_row + ref->effective_num_rows <= margin_top || ref->start_row > (int32_t)margin_bottom;
|
||||
}
|
||||
|
||||
@@ -709,16 +721,19 @@ scroll_filter_margins_func(ImageRef* ref, Image* img, const void* data, CellPixe
|
||||
|
||||
void
|
||||
grman_scroll_images(GraphicsManager *self, const ScrollData *data, CellPixelSize cell) {
|
||||
filter_refs(self, data, true, data->has_margins ? scroll_filter_margins_func : scroll_filter_func, cell);
|
||||
if (self->image_count) {
|
||||
self->layers_dirty = true;
|
||||
modify_refs(self, data, true, data->has_margins ? scroll_filter_margins_func : scroll_filter_func, cell);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
clear_filter_func(ImageRef *ref, Image UNUSED *img, const void UNUSED *data, CellPixelSize cell UNUSED) {
|
||||
clear_filter_func(const ImageRef *ref, Image UNUSED *img, const void UNUSED *data, CellPixelSize cell UNUSED) {
|
||||
return ref->start_row + (int32_t)ref->effective_num_rows > 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
clear_all_filter_func(ImageRef *ref UNUSED, Image UNUSED *img, const void UNUSED *data, CellPixelSize cell UNUSED) {
|
||||
clear_all_filter_func(const ImageRef *ref UNUSED, Image UNUSED *img, const void UNUSED *data, CellPixelSize cell UNUSED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -728,37 +743,37 @@ grman_clear(GraphicsManager *self, bool all, CellPixelSize cell) {
|
||||
}
|
||||
|
||||
static inline bool
|
||||
id_filter_func(ImageRef UNUSED *ref, Image *img, const void *data, CellPixelSize cell UNUSED) {
|
||||
id_filter_func(const ImageRef UNUSED *ref, Image *img, const void *data, CellPixelSize cell UNUSED) {
|
||||
uint32_t iid = *(uint32_t*)data;
|
||||
return img->client_id == iid;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
x_filter_func(ImageRef *ref, Image UNUSED *img, const void *data, CellPixelSize cell UNUSED) {
|
||||
x_filter_func(const ImageRef *ref, Image UNUSED *img, const void *data, CellPixelSize cell UNUSED) {
|
||||
const GraphicsCommand *g = data;
|
||||
return ref->start_column <= (int32_t)g->x_offset - 1 && ((int32_t)g->x_offset - 1) < ((int32_t)(ref->start_column + ref->effective_num_cols));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
y_filter_func(ImageRef *ref, Image UNUSED *img, const void *data, CellPixelSize cell UNUSED) {
|
||||
y_filter_func(const ImageRef *ref, Image UNUSED *img, const void *data, CellPixelSize cell UNUSED) {
|
||||
const GraphicsCommand *g = data;
|
||||
return ref->start_row <= (int32_t)g->y_offset - 1 && ((int32_t)(g->y_offset - 1 < ref->start_row + ref->effective_num_rows));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
z_filter_func(ImageRef *ref, Image UNUSED *img, const void *data, CellPixelSize cell UNUSED) {
|
||||
z_filter_func(const ImageRef *ref, Image UNUSED *img, const void *data, CellPixelSize cell UNUSED) {
|
||||
const GraphicsCommand *g = data;
|
||||
return ref->z_index == g->z_index;
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
point_filter_func(ImageRef *ref, Image *img, const void *data, CellPixelSize cell) {
|
||||
point_filter_func(const ImageRef *ref, Image *img, const void *data, CellPixelSize cell) {
|
||||
return x_filter_func(ref, img, data, cell) && y_filter_func(ref, img, data, cell);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
point3d_filter_func(ImageRef *ref, Image *img, const void *data, CellPixelSize cell) {
|
||||
point3d_filter_func(const ImageRef *ref, Image *img, const void *data, CellPixelSize cell) {
|
||||
return z_filter_func(ref, img, data, cell) && point_filter_func(ref, img, data, cell);
|
||||
}
|
||||
|
||||
|
||||
11
kitty/line.c
11
kitty/line.c
@@ -559,13 +559,14 @@ line_get_char(Line *self, index_type at) {
|
||||
|
||||
void
|
||||
line_set_char(Line *self, unsigned int at, uint32_t ch, unsigned int width, Cursor *cursor, bool UNUSED is_second) {
|
||||
GPUCell *g = self->gpu_cells + at;
|
||||
if (cursor == NULL) {
|
||||
self->gpu_cells[at].attrs = (self->gpu_cells[at].attrs & ATTRS_MASK_WITHOUT_WIDTH) | width;
|
||||
g->attrs = (self->gpu_cells[at].attrs & ATTRS_MASK_WITHOUT_WIDTH) | width;
|
||||
} else {
|
||||
self->gpu_cells[at].attrs = CURSOR_TO_ATTRS(cursor, width & WIDTH_MASK);
|
||||
self->gpu_cells[at].fg = (cursor->fg & COL_MASK);
|
||||
self->gpu_cells[at].bg = (cursor->bg & COL_MASK);
|
||||
self->gpu_cells[at].decoration_fg = cursor->decoration_fg & COL_MASK;
|
||||
g->attrs = CURSOR_TO_ATTRS(cursor, width & WIDTH_MASK);
|
||||
g->fg = cursor->fg & COL_MASK;
|
||||
g->bg = cursor->bg & COL_MASK;
|
||||
g->decoration_fg = cursor->decoration_fg & COL_MASK;
|
||||
}
|
||||
self->cpu_cells[at].ch = ch;
|
||||
memset(self->cpu_cells[at].cc_idx, 0, sizeof(self->cpu_cells[at].cc_idx));
|
||||
|
||||
@@ -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)
|
||||
|
||||
74
kitty/os_window_size.py
Normal file
74
kitty/os_window_size.py
Normal 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
|
||||
@@ -4,24 +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
|
||||
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_height))
|
||||
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:
|
||||
@@ -42,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:
|
||||
@@ -124,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, False)
|
||||
ans.os_window_size = WindowSizes(WindowSize(*w), WindowSize(*h))
|
||||
elif cmd == 'os_window_class':
|
||||
ans.os_window_class = rest
|
||||
else:
|
||||
|
||||
4
kitty/unicode-data.c
generated
4
kitty/unicode-data.c
generated
@@ -1,4 +1,4 @@
|
||||
// unicode data, built from the unicode standard on: 2020-04-06
|
||||
// unicode data, built from the unicode standard on: 2020-08-06
|
||||
// see gen-wcwidth.py
|
||||
#include "data-types.h"
|
||||
|
||||
@@ -8,6 +8,7 @@ START_ALLOW_CASE_RANGE
|
||||
bool
|
||||
is_combining_char(char_type code) {
|
||||
// M category (marks) (2301 codepoints) {{{
|
||||
if (LIKELY(code < 768)) return false;
|
||||
switch(code) {
|
||||
case 0x300 ... 0x36f:
|
||||
return true;
|
||||
@@ -601,6 +602,7 @@ is_combining_char(char_type code) {
|
||||
bool
|
||||
is_ignored_char(char_type code) {
|
||||
// Control characters and non-characters (2339 codepoints) {{{
|
||||
if (LIKELY(0x20 <= code && code <= 0x7e)) return false;
|
||||
switch(code) {
|
||||
case 0x0 ... 0x1f:
|
||||
return true;
|
||||
|
||||
3
kitty/wcwidth-std.h
generated
3
kitty/wcwidth-std.h
generated
@@ -1,4 +1,4 @@
|
||||
// unicode data, built from the unicode standard on: 2020-04-06
|
||||
// unicode data, built from the unicode standard on: 2020-08-06
|
||||
// see gen-wcwidth.py
|
||||
#pragma once
|
||||
#include "data-types.h"
|
||||
@@ -7,6 +7,7 @@ START_ALLOW_CASE_RANGE
|
||||
|
||||
static int
|
||||
wcwidth_std(int32_t code) {
|
||||
if (LIKELY(0x20 <= code && code <= 0x7e)) return 1;
|
||||
switch(code) {
|
||||
// Flags (26 codepoints) {{{
|
||||
case 0x1f1e6 ... 0x1f1ff:
|
||||
|
||||
@@ -380,7 +380,6 @@ class Window:
|
||||
if self.destroyed:
|
||||
return
|
||||
if self.needs_layout or new_geometry.xnum != self.screen.columns or new_geometry.ynum != self.screen.lines:
|
||||
boss = get_boss()
|
||||
self.screen.resize(new_geometry.ynum, new_geometry.xnum)
|
||||
sg = self.update_position(new_geometry)
|
||||
self.needs_layout = False
|
||||
@@ -391,7 +390,7 @@ class Window:
|
||||
self.screen.lines, self.screen.columns,
|
||||
max(0, new_geometry.right - new_geometry.left), max(0, new_geometry.bottom - new_geometry.top))
|
||||
if current_pty_size != self.last_reported_pty_size:
|
||||
boss.child_monitor.resize_pty(self.id, *current_pty_size)
|
||||
get_boss().child_monitor.resize_pty(self.id, *current_pty_size)
|
||||
if not self.pty_resized_once:
|
||||
self.pty_resized_once = True
|
||||
self.child.mark_terminal_ready()
|
||||
|
||||
@@ -3,13 +3,8 @@
|
||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from . import BaseTest
|
||||
|
||||
is32bit = sys.maxsize <= (1 << 32)
|
||||
|
||||
|
||||
class TestTUI(BaseTest):
|
||||
|
||||
@@ -48,7 +43,6 @@ class TestTUI(BaseTest):
|
||||
le.backspace()
|
||||
self.assertTrue(le.pending_bell)
|
||||
|
||||
@unittest.skipIf(is32bit, 'Fails for some unknown reason on 32bit builds')
|
||||
def test_multiprocessing_spawn(self):
|
||||
from kitty.multiprocessing import test_spawn
|
||||
test_spawn()
|
||||
|
||||
11
setup.py
11
setup.py
@@ -696,13 +696,17 @@ def compile_kittens(compilation_database: CompilationDatabase) -> None:
|
||||
kenv, dest, compilation_database, sources, all_headers + ['kitty/data-types.h'])
|
||||
|
||||
|
||||
def build(args: Options, native_optimizations: bool = True) -> None:
|
||||
def init_env_from_args(args: Options, native_optimizations: bool = False) -> None:
|
||||
global env
|
||||
env = init_env(
|
||||
args.debug, args.sanitize, native_optimizations, args.profile,
|
||||
args.egl_library, args.startup_notification_library, args.canberra_library,
|
||||
args.extra_logging
|
||||
)
|
||||
|
||||
|
||||
def build(args: Options, native_optimizations: bool = True) -> None:
|
||||
init_env_from_args(args, native_optimizations)
|
||||
sources, headers = find_c_files()
|
||||
compile_c_extension(
|
||||
kitty_env(), 'kitty/fast_data_types', args.compilation_database, sources, headers
|
||||
@@ -1041,7 +1045,7 @@ def option_parser() -> argparse.ArgumentParser: # {{{
|
||||
'action',
|
||||
nargs='?',
|
||||
default=Options.action,
|
||||
choices='build test linux-package kitty.app linux-freeze macos-freeze clean'.split(),
|
||||
choices='build test linux-package kitty.app linux-freeze macos-freeze build-launcher clean'.split(),
|
||||
help='Action to perform (default is build)'
|
||||
)
|
||||
p.add_argument(
|
||||
@@ -1156,6 +1160,9 @@ def main() -> None:
|
||||
create_minimal_macos_bundle(args, launcher_dir)
|
||||
else:
|
||||
build_launcher(args, launcher_dir=launcher_dir)
|
||||
elif args.action == 'build-launcher':
|
||||
init_env_from_args(args, False)
|
||||
build_launcher(args, launcher_dir=launcher_dir)
|
||||
elif args.action == 'linux-package':
|
||||
build(args, native_optimizations=False)
|
||||
package(args, bundle_type='linux-package')
|
||||
|
||||
Reference in New Issue
Block a user