diff --git a/docs/changelog.rst b/docs/changelog.rst index 57595dd70..f4ce5cb20 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -193,6 +193,8 @@ Detailed list of changes - Wayland: Use hold gestures to cancel momentum scrolling when fingers are placed on the trackpad, for a more natural kinetic scrolling experience (:iss:`9863`) +- macOS: Switch to new Tahoe style application icon with different background in light and dark modes + - Fix thickness of diagonal lines in box drawing characters not the same as horizontal/vertical lines (:iss:`9719`) - Graphics protocol: Fix crash when handling invalid PNG image with direct transmission diff --git a/logo/Assets.car b/logo/Assets.car new file mode 100644 index 000000000..8b955776a Binary files /dev/null and b/logo/Assets.car differ diff --git a/logo/attribution.txt b/logo/attribution.txt deleted file mode 100644 index f48eb7a45..000000000 --- a/logo/attribution.txt +++ /dev/null @@ -1,8 +0,0 @@ -Attribution -########### - -- Name: macOS Big Sur Icon Template -- Author: Václav Vančura -- Source: https://www.figma.com/community/file/857303226040719059 -- License: https://creativecommons.org/licenses/by/4.0/ -- Modification: Replaced the template logo with kitty's diff --git a/logo/kitty-128.png b/logo/kitty-128.png index 2796a969a..8ac0efbd5 100644 Binary files a/logo/kitty-128.png and b/logo/kitty-128.png differ diff --git a/logo/kitty-framed.svg b/logo/kitty-framed.svg deleted file mode 100644 index b12d2b90d..000000000 --- a/logo/kitty-framed.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/logo/kitty.icns b/logo/kitty.icns new file mode 100644 index 000000000..7cc5bc655 Binary files /dev/null and b/logo/kitty.icns differ diff --git a/logo/kitty.iconset/icon_128x128.png b/logo/kitty.iconset/icon_128x128.png deleted file mode 100644 index 90fc439eb..000000000 Binary files a/logo/kitty.iconset/icon_128x128.png and /dev/null differ diff --git a/logo/kitty.iconset/icon_128x128@2x.png b/logo/kitty.iconset/icon_128x128@2x.png deleted file mode 100644 index 99ae2b862..000000000 Binary files a/logo/kitty.iconset/icon_128x128@2x.png and /dev/null differ diff --git a/logo/kitty.iconset/icon_16x16.png b/logo/kitty.iconset/icon_16x16.png deleted file mode 100644 index dd2449602..000000000 Binary files a/logo/kitty.iconset/icon_16x16.png and /dev/null differ diff --git a/logo/kitty.iconset/icon_16x16@2x.png b/logo/kitty.iconset/icon_16x16@2x.png deleted file mode 100644 index f3a254ce6..000000000 Binary files a/logo/kitty.iconset/icon_16x16@2x.png and /dev/null differ diff --git a/logo/kitty.iconset/icon_256x256.png b/logo/kitty.iconset/icon_256x256.png deleted file mode 100644 index 99ae2b862..000000000 Binary files a/logo/kitty.iconset/icon_256x256.png and /dev/null differ diff --git a/logo/kitty.iconset/icon_256x256@2x.png b/logo/kitty.iconset/icon_256x256@2x.png deleted file mode 100644 index a01944c24..000000000 Binary files a/logo/kitty.iconset/icon_256x256@2x.png and /dev/null differ diff --git a/logo/kitty.iconset/icon_32x32.png b/logo/kitty.iconset/icon_32x32.png deleted file mode 100644 index f3a254ce6..000000000 Binary files a/logo/kitty.iconset/icon_32x32.png and /dev/null differ diff --git a/logo/kitty.iconset/icon_32x32@2x.png b/logo/kitty.iconset/icon_32x32@2x.png deleted file mode 100644 index 0b245b95e..000000000 Binary files a/logo/kitty.iconset/icon_32x32@2x.png and /dev/null differ diff --git a/logo/kitty.iconset/icon_512x512.png b/logo/kitty.iconset/icon_512x512.png deleted file mode 100644 index a01944c24..000000000 Binary files a/logo/kitty.iconset/icon_512x512.png and /dev/null differ diff --git a/logo/kitty.iconset/icon_512x512@2x.png b/logo/kitty.iconset/icon_512x512@2x.png deleted file mode 100644 index 54c760787..000000000 Binary files a/logo/kitty.iconset/icon_512x512@2x.png and /dev/null differ diff --git a/logo/kitty.png b/logo/kitty.png index d536c38ba..a4cdcf8cf 100644 Binary files a/logo/kitty.png and b/logo/kitty.png differ diff --git a/logo/make.py b/logo/make.py index 3aff854ab..a93fa20a8 100755 --- a/logo/make.py +++ b/logo/make.py @@ -2,48 +2,142 @@ # vim:fileencoding=utf-8 # License: GPL v3 Copyright: 2017, Kovid Goyal +import json import os import shutil import subprocess +import sys +from copy import deepcopy +from typing import Any +SRC = 'kitty.svg' base = os.path.dirname(os.path.abspath(__file__)) -unframed_src = os.path.join(base, 'kitty.svg') -framed_src = os.path.join(base, 'kitty-framed.svg') + +# To generate this template create an icon using Icon Composer on macOS and in +# the saved .icon (which is a folder) look for icon.js +icon_settings:dict[str, Any] = { + 'fill-specializations' : [ + { + 'value' : { + 'automatic-gradient' : 'extended-gray:1.00000,1.00000' + } + }, + { + 'appearance' : 'dark', + 'value' : { + 'automatic-gradient' : 'display-p3:0.20500,0.20500,0.20500,1.00000' + } + } + ], + 'groups' : [ + { + 'layers' : [ + { + 'blend-mode' : 'normal', + 'glass' : False, + 'hidden' : False, + 'image-name' : 'icon.svg', + 'name' : 'icon', + 'opacity' : 1, + 'position' : { + 'scale' : 0.9, + 'translation-in-points' : [ + 0, + 0 + ] + } + } + ], + 'shadow' : { + 'kind' : 'neutral', + 'opacity' : 0.5 + }, + 'translucency' : { + 'enabled' : True, + 'value' : 0.5 + } + } + ], + 'supported-platforms' : { + 'circles' : [ + 'watchOS' + ], + 'squares' : 'shared' + } +} + +def abspath(x: str) -> str: + return os.path.abspath(os.path.join(base, x)) -def abspath(x): - return os.path.join(base, x) - - -def run(*args): +def run(*args: str) -> None: try: subprocess.check_call(args) except OSError: raise SystemExit(f'You are missing the {args[0]} program needed to generate the kitty logo') -def render(output, sz=256, src=unframed_src): +def get_svg_viewbox(file_path: str) -> tuple[float, ...]: + import xml.etree.ElementTree as ET + tree = ET.parse(file_path) + root = tree.getroot() + viewbox = root.get('viewBox') + if viewbox: + return tuple(float(x) for x in viewbox.split()) + width = root.get('width') + height = root.get('height') + return (0.0, 0.0, float(width or 0), float(height or 0)) + + +def create_icon(name: str, svg_path: str, output_path: str) -> str: + view_box = get_svg_viewbox(svg_path) + sz = view_box[-1] + scale = 0.9 * 1024 / sz + icon_dir = os.path.join(output_path, f'{name}.icon') + if os.path.exists(icon_dir): + shutil.rmtree(icon_dir) + os.mkdir(icon_dir) + s = deepcopy(icon_settings) + for group in s['groups']: + for layer in group['layers']: + layer['image-name'] = os.path.basename(svg_path) + layer['name'] = name + layer['position']['scale'] = scale + with open(os.path.join(icon_dir, 'icon.json'), 'w') as f: + json.dump(s, f, indent=2) + assets_dir = os.path.join(icon_dir, 'Assets') + os.mkdir(assets_dir) + shutil.copy(svg_path, assets_dir) + return icon_dir + + +def create_assets() -> None: + actool = [ + 'xcrun', 'actool', '--warnings', '--platform', 'macosx', '--compile', base, + '--minimum-deployment-target', '15.0', '--output-partial-info-plist', '/dev/stdout', + ] + icon = create_icon('kitty', abspath(SRC), base) + run(*(actool + ['--app-icon', 'kitty', icon])) + shutil.rmtree(icon) + + +def render(output: str, sz: int = 256) -> None: + src = abspath(SRC) print(f'Rendering {os.path.basename(src)} at {sz}x{sz}...') run('rsvg-convert', '-w', str(sz), '-h', str(sz), '-o', output, src) run('optipng', '-quiet', '-o7', '-strip', 'all', output) -def main(): +def main() -> None: + if 'darwin' in sys.platform.lower(): + create_assets() + if sys.argv[-1] == 'remote-macos': + return + else: + run('ssh', 'ox', 'zsh', '-ilc', '~/bin/update-kitty && python3 ~/kitty-src/logo/make.py remote-macos') + run('rsync', '-avz', '--include=*.icns', '--include=*.car', '--exclude=*', 'ox:~/kitty-src/logo/', base + '/') render(abspath('kitty.png')) render(abspath('kitty-128.png'), sz=128) - iconset = abspath('kitty.iconset') - if os.path.exists(iconset): - shutil.rmtree(iconset) - os.mkdir(iconset) - os.chdir(iconset) - for sz in (16, 32, 64, 128, 256, 512, 1024): - iname = os.path.join(iconset, 'icon_{0}x{0}.png'.format(sz)) - iname2x = 'icon_{0}x{0}@2x.png'.format(sz // 2) - render(iname, sz, src=framed_src) - if sz > 16 and sz != 128: - shutil.copy2(iname, iname2x) - if sz in (64, 1024): - os.remove(iname) if __name__ == '__main__': diff --git a/setup.py b/setup.py index 5844c4e31..eb8c699cc 100755 --- a/setup.py +++ b/setup.py @@ -1726,6 +1726,7 @@ def macos_info_plist(for_quake: str = '') -> bytes: CFBundleAllowMixedLocalizations=True, TICapsLockLanguageSwitchCapable=True, # User Interface and Graphics + CFBundleIconName=appname, CFBundleIconFile=f'{appname}.icns', NSHighResolutionCapable=True, NSSupportsAutomaticGraphicsSwitching=True, @@ -1769,24 +1770,8 @@ def macos_info_plist(for_quake: str = '') -> bytes: def create_macos_app_icon(where: str = 'Resources') -> None: - iconset_dir = os.path.abspath(os.path.join('logo', f'{appname}.iconset')) - icns_dir = os.path.join(where, f'{appname}.icns') - try: - subprocess.check_call([ - 'iconutil', '-c', 'icns', iconset_dir, '-o', icns_dir - ]) - except FileNotFoundError: - print(f'{error("iconutil not found")}, using png2icns (without retina support) to convert the logo', file=sys.stderr) - subprocess.check_call([ - 'png2icns', icns_dir - ] + [os.path.join(iconset_dir, logo) for logo in [ - # png2icns does not support retina icons, so only pass the non-retina icons - 'icon_16x16.png', - 'icon_32x32.png', - 'icon_128x128.png', - 'icon_256x256.png', - 'icon_512x512.png', - ]]) + for x in (f'{appname}.icns', 'Assets.car'): + shutil.copy(os.path.join('logo', x), os.path.join(where, x)) quake_name = f'{appname}-quick-access'