Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99517bbb6c | ||
|
|
1ac77c4045 | ||
|
|
61e0ab126f | ||
|
|
b6b079b8f0 | ||
|
|
f9b35addae | ||
|
|
8425ceb709 | ||
|
|
fa77bc2514 | ||
|
|
84e96f175c | ||
|
|
09c1e312cb | ||
|
|
b14133bbec |
No files matched your search
@@ -5,15 +5,15 @@ These are my config files for macOS and KDE, managed with GNU Stow. You need `st
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
git clone https://github.com/vokhactri/.dotfiles.git "$HOME/.dotfiles"
|
||||
git clone https://git.trivk.dev/tri/.dotfiles.git "$HOME/.dotfiles"
|
||||
cd "$HOME/.dotfiles"
|
||||
```
|
||||
|
||||
The packages are split into three groups:
|
||||
|
||||
- [common/](common/README.md) has Git, Micro, mpv, npm, Starship and Zsh.
|
||||
- [mac/](mac/README.md) has Ghostty and the original Fastfetch config.
|
||||
- [kde/](kde/README.md) has the Darwin Breeze theme, Helium, Konsole Fastfetch, Spectacle and tray icons.
|
||||
- [common/](common/README.md) has Fastfetch, Git, Micro, mpv, npm, Starship and Zsh.
|
||||
- [mac/](mac/README.md) has Ghostty.
|
||||
- [kde/](kde/README.md) has the Darwin Breeze theme, Helium, Spectacle and tray icons.
|
||||
|
||||
Install all of `common`, then the group for your platform:
|
||||
|
||||
@@ -32,10 +32,10 @@ You don't have to install everything. List only the packages you want:
|
||||
```sh
|
||||
stow -d common -t "$HOME" git zsh starship
|
||||
stow -d mac -t "$HOME" ghostty
|
||||
stow -d kde -t "$HOME" spectacle fastfetch
|
||||
stow -d kde -t "$HOME" spectacle
|
||||
```
|
||||
|
||||
`-d` tells Stow which group to read from. `-t` puts the symlinks in your home directory. You can mix packages from different groups. Fastfetch is the exception. Install `mac/fastfetch` or `kde/fastfetch`, never both.
|
||||
`-d` tells Stow which group to read from. `-t` puts the symlinks in your home directory. You can mix packages from different groups.
|
||||
|
||||
### Previewing and removing
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
# Common packages
|
||||
|
||||
Shared configuration for Git, Micro, mpv, npm, Starship, and Zsh.
|
||||
Shared configuration for Fastfetch, Git, Micro, mpv, npm, Starship, and Zsh.
|
||||
From the repository root, install all shared packages:
|
||||
|
||||
```sh
|
||||
@@ -14,5 +14,5 @@ stow -d common -t "$HOME" git
|
||||
stow -d common -t "$HOME" zsh starship
|
||||
```
|
||||
|
||||
Choose any of `git`, `micro`, `mpv`, `npm`, `starship`, and `zsh`.
|
||||
Choose any of `fastfetch`, `git`, `micro`, `mpv`, `npm`, `starship`, and `zsh`.
|
||||
Reload Zsh with `exec zsh` after installing its configuration.
|
||||
@@ -0,0 +1 @@
|
||||
_Ga=T,f=100,t=d,c=20,r=10,q=2,m=1;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\_Gm=1;R+I1tGnTxpUIALupermOJgMSCAQCocgRAEVRUABcUMncKQEgIgA4GU8z+1WrBo888gjLdf/xh+gubA7cBZ8+fRpWr14No0ePhnvvvReSk5PB39/Wc1902jOKAUwTNG7QRosKsLbBpaSkUJs2mDOYVT14e/tqEYBOnTq5JACkCMByagdMIBAIBGciAJUA4KQrPQAEgV26dIl1vhs5ciScPXvWlOiR8LBMEC9vRH67du2CMWPGsEhBpUqVDJEBb53BMDAgFOJjmrESvNIkBPAxMUqRmdqDmR/Fc8YIiIsmQFEFME/u6UAgEAgEQmEFQAAAbBcc7UoVgBFI9GI0rkgVOFpGcWC8P4wQfPvtt3DrrbeyUjpblYEneEkTBNE8iBP7cGCPo7bCxSsAsFPgEDZSWK4EePrpp7Vj5GQKQEwFnCJXdBAIBAKBUJROgD+rZHK1qGkAYx8AmfTlv9/obo3lhEIUCEEg49ChQ/DOO+9Aw4YN7aIC4jqO7MWIAEsNqK16izsaICYJ4uMnJbbWPccvvvjCFQGgSAObvlD7AFAjIAKBQCAUeQ7A2yqZFLkRkBmRuzDtzu6+xKWZGMDfz5o1Czp27OhQCGBqIKVhtq65UHFGAjD6gJEIjErIfRHmzp1rNyypaIdGa9r0P2oFTCAQCARnBUBHlUxEHwBrGNwiGKMM8nhhARy927NnT10PAjk1gB0Ic1v3ZYa84hIBokSxS/5QqFa5jvZc/Pz8YNu2ba6UAcqNgIaRACAQCASCsymA8gBw3NVhQMUBo3fAGBVYv3498wnIZYTCeY8dB9EkKEcC3C0AhA8gJChce05YLnn58mXt9ThxDGQB0E54AOjjTyAQCARLine truncated
|
||||
File renamed without changes.
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 138 KiB |
+1
-1
@@ -11,7 +11,7 @@
|
||||
},
|
||||
"logo": {
|
||||
"type": "raw",
|
||||
"source": "~/.config/fastfetch/albedo-konsole.kitty",
|
||||
"source": "~/.config/fastfetch/albedo.kitty",
|
||||
"width": 20,
|
||||
"height": 10
|
||||
},
|
||||
File renamed without changes.
@@ -0,0 +1,17 @@
|
||||
# Fastfetch
|
||||
|
||||
```sh
|
||||
stow -d common -t "$HOME" fastfetch
|
||||
```
|
||||
|
||||
The logo is `albedo.png`, sent inline through the kitty graphics protocol from
|
||||
the pre-encoded `albedo.kitty`. This works in Ghostty and Kwi. The
|
||||
`kitty-direct` logo type is not used because Kwi ignores images passed as a
|
||||
file path.
|
||||
|
||||
After changing `albedo.png` or the logo size in `config.jsonc`, regenerate the
|
||||
logo from the repository root:
|
||||
|
||||
```sh
|
||||
python3 common/fastfetch/build.py
|
||||
```
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Encode albedo.png as kitty graphics escapes for fastfetch's "raw" logo.
|
||||
|
||||
fastfetch's "kitty-direct" logo sends the terminal a file path (t=f), which
|
||||
Kwi ignores. This file carries the PNG inline (t=d) instead, so it works in
|
||||
any terminal with the kitty graphics protocol, Ghostty and Kwi included. q=2
|
||||
keeps the terminal from answering. Rerun after changing the image or the
|
||||
logo size.
|
||||
"""
|
||||
|
||||
import base64
|
||||
from pathlib import Path
|
||||
|
||||
DIR = Path(__file__).resolve().parent / ".config/fastfetch"
|
||||
# Logo size in cells; keep in sync with "width" and "height" in config.jsonc.
|
||||
COLS, ROWS = 20, 10
|
||||
|
||||
|
||||
def encode(png: bytes) -> bytes:
|
||||
data = base64.b64encode(png)
|
||||
chunks = [data[i : i + 4096] for i in range(0, len(data), 4096)]
|
||||
out = bytearray()
|
||||
for n, chunk in enumerate(chunks):
|
||||
more = int(n < len(chunks) - 1)
|
||||
if n == 0:
|
||||
keys = b"a=T,f=100,t=d,c=%d,r=%d,q=2,m=%d" % (COLS, ROWS, more)
|
||||
else:
|
||||
keys = b"m=%d" % more
|
||||
out += b"\x1b_G" + keys + b";" + chunk + b"\x1b\\"
|
||||
return bytes(out)
|
||||
|
||||
|
||||
(DIR / "albedo.kitty").write_bytes(encode((DIR / "albedo.png").read_bytes()))
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
min-release-age=7 ; 7 days for npm
|
||||
minimum-release-age=10080 ; 7 days in minutes for pnpm
|
||||
min-release-age=1 ; 1 day for npm
|
||||
minimum-release-age=1440 ; 1 day in minutes for pnpm
|
||||
@@ -5,3 +5,6 @@ export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
|
||||
|
||||
XDG_BIN_HOME="${XDG_BIN_HOME:-$HOME/.local/bin}"
|
||||
ZDOTDIR="$XDG_CONFIG_HOME/zsh"
|
||||
|
||||
# Per-machine settings that stay out of the repo, like PATH entries for a VPS.
|
||||
[ -r "$XDG_CONFIG_HOME/zshenv.local" ] && . "$XDG_CONFIG_HOME/zshenv.local"
|
||||
+7
-9
@@ -9,16 +9,15 @@ From the repository root, install all KDE packages:
|
||||
Or choose individual packages:
|
||||
|
||||
```sh
|
||||
stow -d kde -t "$HOME" spectacle fastfetch
|
||||
stow -d kde -t "$HOME" spectacle helium
|
||||
```
|
||||
|
||||
| Package | Details |
|
||||
| ---------------------------------- | -------------------------------------------------------- |
|
||||
| [theme](theme/README.md) | Darwin Breeze KDE colors and generated app themes |
|
||||
| [helium](helium/README.md) | Browser flags and the generated Helium theme |
|
||||
| [fastfetch](fastfetch/README.md) | Konsole configuration and a pre-scaled inline image logo |
|
||||
| [helium](helium/README.md) | Browser flags; colors come from GTK |
|
||||
| [spectacle](spectacle/README.md) | Screenshots to clipboard with a notification, no preview |
|
||||
| [tray-icons](tray-icons/README.md) | Ngó Sen and qBittorrent tray icons |
|
||||
| [tray-icons](tray-icons/README.md) | Ngó Sen, NetBird and qBittorrent tray icons |
|
||||
|
||||
Theme and Spectacle need an additional apply step after stowing their package:
|
||||
|
||||
@@ -29,9 +28,8 @@ Theme and Spectacle need an additional apply step after stowing their package:
|
||||
./kde/spectacle/apply.py
|
||||
```
|
||||
|
||||
The apply scripts require a running KDE Plasma 6 session. Ngó Sen icons need
|
||||
an additional install step described in the tray-icons README.
|
||||
The apply scripts require a running KDE Plasma 6 session. Ngó Sen and NetBird
|
||||
icons need an additional install step described in the tray-icons README.
|
||||
|
||||
Packages can be selected independently. Helium includes its generated theme;
|
||||
it does not require the KDE theme to be installed. Choose either
|
||||
`kde/fastfetch` or `mac/fastfetch`; both own `~/.config/fastfetch/`.
|
||||
Packages can be selected independently; Helium follows the Darwin Breeze
|
||||
colors only when the theme is applied.
|
||||
@@ -1 +0,0 @@
|
||||
_Ga=T,f=100,t=d,c=20,r=10,q=2,m=1;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\_Gm=1;2CzUiM53eKtBKKIrpLeyTzEjo54ifjUgpOfqaqxO8jgVGiX/zaZiv5kqvU+SQXJkYerUqQJ8bk6hBL52goHe22igSfbziCfL1U+A8b9pkDCguZ5MtWrGcHcPISB6wdTUCXr61qhS1Rz2toGIDGqAGlFZwkXD+4cTY/IXjiLOeTM831+7dm21Fl2BxbgZUkSoUB/8bzWV3tdEXvGvMd+K5SvE5Lg6hgi3xttErq7O+mFsWCNYmDoTAzUv4DbR7n+PHaXP107qKAyh0qXLw9HBCdUTYpDZpB6aZ9ZH3TopiAyPgJuzn9g34ukcj7jwTGGps69QKvHRVBgnHPbj+xw+fPhrIFQtyh7yeBUvBOH/salErz6t8qvyAL9UxBC348dPoHyFcrCx8JCYjybrP2Eq1v9sLN0RHZqB9MR2mjow7MvjRyk5obWUavXe39mCgN0E5sZuSEtNxoK543Ht4l48fXCeqJtu5/lVvHx6GfdvncTp45sxb/ZvaNemOXy9Auh+fIk5U4mdvxTxaV5UzM5erlEoUvRTsSdZ1v00RCg/chkuJW5cWBD9/9KQ73IZqV7liv7z+PETeHl7okpFY3lL5N93JitAqZvSCa4OoQQWD3g4xcLO0o9A4AVbKy/xaGflD3vrELKY676zFIfCqjGhjeDjGYgFc8YJsL14fAkP75zBnZzjuHXzGPWjot/JPYFHd8/i1VMC5YvruHFlP2ZMHY60Wsn0+x5wc4ghADanhdBKLA5jA3tYWVvi9u3bUI+HDELFKf+TAsBCnfA/aMhPnXeHnL2srHJl1Xfu0lmUPpOUeEXk/T3gsd4V7FubAOdPYtATdWun4MeBvTBn1hisXTUTmzfLine truncated
|
||||
@@ -1,26 +0,0 @@
|
||||
# Fastfetch for Konsole
|
||||
|
||||
From the repository root:
|
||||
|
||||
```sh
|
||||
stow -d kde -t "$HOME" fastfetch
|
||||
```
|
||||
|
||||
The configuration, source PNG, and generated logo live in
|
||||
`kde/fastfetch/.config/fastfetch/`. The generated logo is included, so a new
|
||||
machine does not need to run the build script.
|
||||
|
||||
Choose either this package or `mac/fastfetch`; both own `~/.config/fastfetch/`.
|
||||
|
||||
Konsole needs inline image data instead of the original `kitty-direct` file
|
||||
transfer. The committed `albedo-konsole.kitty` logo is pre-scaled to 20 × 10
|
||||
cells to avoid grainy terminal scaling.
|
||||
|
||||
After changing `albedo.png`, the logo dimensions, or Konsole's font, update
|
||||
the cell size in `build.py` and regenerate the logo from the repository root:
|
||||
|
||||
```sh
|
||||
python3 kde/fastfetch/build.py
|
||||
```
|
||||
|
||||
The build script requires `vipsthumbnail` from libvips.
|
||||
@@ -1,57 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Encode albedo.png as kitty graphics escapes for fastfetch's "raw" logo.
|
||||
|
||||
fastfetch's "kitty-direct" logo sends the terminal a file path (t=f). Konsole
|
||||
only accepts inline data (t=d) and answers t=f with ENOTSUPPORTED, which lands
|
||||
on the prompt as typed input. These files carry the PNG inline instead, with
|
||||
q=2 so the terminal never answers at all.
|
||||
|
||||
.config/fastfetch/albedo-konsole.kitty pre-scaled for Konsole
|
||||
|
||||
Konsole stretches the image to the c x r cell box with nearest-neighbour
|
||||
scaling, at logical (not device) pixel size, so a 512px source turns grainy.
|
||||
The Konsole copy is resized with Lanczos to exactly that box, which leaves
|
||||
Konsole nothing to scale. Rerun after changing the image, the logo size or the
|
||||
Konsole font.
|
||||
"""
|
||||
|
||||
import base64
|
||||
import subprocess
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
PKG = Path(__file__).resolve().parent
|
||||
DIR = PKG / ".config/fastfetch"
|
||||
SOURCE = DIR / "albedo.png"
|
||||
# Logo size in cells; keep in sync with "width" and "height" in config.jsonc.
|
||||
COLS, ROWS = 20, 10
|
||||
# Konsole's cell size in logical pixels for JetBrainsMono Nerd Font 10pt
|
||||
# (QFontMetrics: average advance of Konsole's REPCHAR, and height()).
|
||||
KONSOLE_CELL = 8, 17
|
||||
|
||||
|
||||
def encode(png: bytes, dst: Path) -> None:
|
||||
data = base64.b64encode(png)
|
||||
chunks = [data[i : i + 4096] for i in range(0, len(data), 4096)]
|
||||
out = bytearray()
|
||||
for n, chunk in enumerate(chunks):
|
||||
more = int(n < len(chunks) - 1)
|
||||
if n == 0:
|
||||
keys = b"a=T,f=100,t=d,c=%d,r=%d,q=2,m=%d" % (COLS, ROWS, more)
|
||||
else:
|
||||
keys = b"m=%d" % more
|
||||
out += b"\x1b_G" + keys + b";" + chunk + b"\x1b\\"
|
||||
dst.write_bytes(out)
|
||||
|
||||
|
||||
def resize(width: int, height: int) -> bytes:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
out = Path(tmp) / "out.png"
|
||||
subprocess.run(
|
||||
["vipsthumbnail", SOURCE, "--size", f"{width}x{height}!", "-o", out],
|
||||
check=True,
|
||||
)
|
||||
return out.read_bytes()
|
||||
|
||||
|
||||
encode(resize(COLS * KONSOLE_CELL[0], ROWS * KONSOLE_CELL[1]), DIR / "albedo-konsole.kitty")
|
||||
@@ -2,5 +2,7 @@
|
||||
--ozone-platform-hint=auto
|
||||
--enable-features=AcceleratedVideoDecodeLinuxGL,AcceleratedVideoDecodeLinuxZeroCopyGL,AcceleratedVideoEncoder
|
||||
|
||||
# Darwin Breeze theme, generated by kde/theme/build.py
|
||||
--load-extension=~/.local/share/helium-themes/darwinbreeze
|
||||
# Don't tag surfaces as sRGB. KWin shows tagged sRGB through a gamma 2.2
|
||||
# curve, which lifts dark grays (40 -> 44), so the tab strip would come out
|
||||
# lighter than KDE title bars.
|
||||
--disable-features=WaylandWpColorManagerV1
|
||||
@@ -1,2 +0,0 @@
|
||||
# Helium caches the built theme next to the manifest.
|
||||
Cached Theme.pak
|
||||
@@ -1,100 +0,0 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "Darwin Breeze",
|
||||
"version": "1.0",
|
||||
"description": "Generated by kde/theme/build.py from DarwinBreezeDark.colors",
|
||||
"theme": {
|
||||
"colors": {
|
||||
"frame": [
|
||||
35,
|
||||
35,
|
||||
35
|
||||
],
|
||||
"frame_inactive": [
|
||||
35,
|
||||
35,
|
||||
35
|
||||
],
|
||||
"frame_incognito": [
|
||||
35,
|
||||
35,
|
||||
35
|
||||
],
|
||||
"frame_incognito_inactive": [
|
||||
35,
|
||||
35,
|
||||
35
|
||||
],
|
||||
"toolbar": [
|
||||
35,
|
||||
35,
|
||||
35
|
||||
],
|
||||
"background_tab": [
|
||||
60,
|
||||
60,
|
||||
60
|
||||
],
|
||||
"background_tab_inactive": [
|
||||
60,
|
||||
60,
|
||||
60
|
||||
],
|
||||
"tab_text": [
|
||||
223,
|
||||
223,
|
||||
223
|
||||
],
|
||||
"tab_background_text": [
|
||||
223,
|
||||
223,
|
||||
223
|
||||
],
|
||||
"tab_background_text_inactive": [
|
||||
155,
|
||||
155,
|
||||
155
|
||||
],
|
||||
"toolbar_text": [
|
||||
223,
|
||||
223,
|
||||
223
|
||||
],
|
||||
"toolbar_button_icon": [
|
||||
223,
|
||||
223,
|
||||
223
|
||||
],
|
||||
"bookmark_text": [
|
||||
223,
|
||||
223,
|
||||
223
|
||||
],
|
||||
"omnibox_background": [
|
||||
24,
|
||||
24,
|
||||
24
|
||||
],
|
||||
"omnibox_text": [
|
||||
222,
|
||||
222,
|
||||
222
|
||||
],
|
||||
"ntp_background": [
|
||||
24,
|
||||
24,
|
||||
24
|
||||
],
|
||||
"ntp_text": [
|
||||
222,
|
||||
222,
|
||||
222
|
||||
],
|
||||
"ntp_link": [
|
||||
63,
|
||||
157,
|
||||
255
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,14 @@
|
||||
# Helium
|
||||
|
||||
Browser flags and the generated Darwin Breeze theme. From the repository root:
|
||||
Browser flags for hardware video decoding on Wayland and for colors that
|
||||
match KDE apps. From the repository root:
|
||||
|
||||
```sh
|
||||
stow -d kde -t "$HOME" helium
|
||||
```
|
||||
|
||||
The theme files are included, so the KDE `theme` package does not need to be
|
||||
stowed to use Helium's theme. To regenerate its colors from the shared color
|
||||
scheme, run `python3 kde/theme/build.py` and restart Helium.
|
||||
Helium takes its colors and window buttons from GTK. In Settings →
|
||||
Appearance, set Theme to GTK and turn off "Use system title bar and borders".
|
||||
With the KDE `theme` package applied, GTK follows the Darwin Breeze colors and
|
||||
the window buttons match KWin's; see
|
||||
[Darwin Breeze → Helium notes](../theme/README.md#helium-notes).
|
||||
Regular → Executable
+1
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env xdg-open
|
||||
[Desktop Entry]
|
||||
GenericName=Screenshot Capture Utility
|
||||
Name=Spectacle
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/* Helium (Chromium) with its GTK theme. Chromium adds a "chromium" class to
|
||||
every node of the GTK style contexts it reads colors from, so these rules
|
||||
reach Helium and no other GTK app.
|
||||
|
||||
In the compact layout, the address bar takes the text field color and the
|
||||
segment with the extension and window buttons takes the window color,
|
||||
which Chromium resolves to the darker view color. Both get the title bar
|
||||
color, so the strip reads as one bar like a KDE title bar. */
|
||||
window.background.chromium,
|
||||
textview.view.chromium {
|
||||
background-color: @theme_bg_color_breeze;
|
||||
}
|
||||
+28
-18
@@ -23,11 +23,11 @@ stow -d kde -t "$HOME" theme
|
||||
```
|
||||
|
||||
`apply.sh` regenerates the app themes, applies the global theme, hides the
|
||||
line under the title bar, turns off the wallpaper accent color and publishes
|
||||
the T3 Code theme and installs the VS Code extension. Restart Helium
|
||||
afterwards; T3 Code switches on its own. In VS Code, pick "Darwin Breeze Dark"
|
||||
once under Preferences → Color Theme; after later color changes, run Developer:
|
||||
Reload Window.
|
||||
line under the title bar, turns off the wallpaper accent color, gives Helium
|
||||
the KWin title buttons and an even tab strip, publishes the T3 Code theme and
|
||||
installs the VS Code extension. Restart Helium afterwards; T3 Code switches on its own. In VS
|
||||
Code, pick "Darwin Breeze Dark" once under Preferences → Color Theme; after
|
||||
later color changes, run Developer: Reload Window.
|
||||
|
||||
Telegram has to import its theme by hand: Settings → Chat Settings → Chat
|
||||
background → Choose from file, then pick
|
||||
@@ -49,7 +49,7 @@ Edit it, then run `./kde/theme/apply.sh` again. Everything else follows:
|
||||
| Qt / KDE apps | the color scheme itself |
|
||||
| GTK apps | Breeze GTK, which `kde-gtk-config` syncs from the scheme |
|
||||
| Tray icons in `kde/tray-icons/` | `ColorScheme-Text`, recolored by Plasma |
|
||||
| Helium | `../helium/.local/share/helium-themes/`, generated by `build.py` |
|
||||
| Helium | Breeze GTK, through Helium's GTK theme (see [Helium notes](#helium-notes)) |
|
||||
| T3 Code | `t3/darwin-breeze.json`, generated by `build.py` and published with `t3 theme set` |
|
||||
| VS Code | `vscode/package.json` and `vscode/themes/`, generated by `build.py`, packed into `darwin-breeze.vsix` and installed by `apply.sh` |
|
||||
| Telegram | `telegram/DarwinBreezeDark.tdesktop-theme`, built by `build.py` and imported by hand |
|
||||
@@ -81,7 +81,7 @@ are built by `build.py` instead. Don't edit generated files by hand.
|
||||
are, without gamma compensation, so code looks the same in both apps.
|
||||
- The terminal palette is generated from the color scheme.
|
||||
- VS Code is Electron, so its workbench colors get the same gamma
|
||||
compensation as Helium and T3 Code.
|
||||
compensation as T3 Code.
|
||||
- The `.vsix` isn't committed; `build.py` packs it from `vscode/`.
|
||||
|
||||
## Telegram notes
|
||||
@@ -94,24 +94,34 @@ are built by `build.py` instead. Don't edit generated files by hand.
|
||||
colors, are kept as night has them.
|
||||
- The chat list, top bar and compose bar use the window color; the chat
|
||||
behind the bubbles and the folder strip use the darker view color.
|
||||
- Telegram is a Qt app, so unlike Helium and T3 Code it needs no gamma
|
||||
- Telegram is a Qt app, so unlike T3 Code and VS Code it needs no gamma
|
||||
compensation.
|
||||
- The `.tdesktop-theme` is a zip, so it isn't committed; `build.py` builds it
|
||||
from the night palette and the color scheme.
|
||||
|
||||
## Helium notes
|
||||
|
||||
- Helium loads the theme from `~/.local/share/helium-themes/darwinbreeze`
|
||||
through `--load-extension` in `kde/helium/.config/helium-browser-flags.conf`.
|
||||
Install it separately with `stow -d kde -t "$HOME" helium`.
|
||||
- In Helium's compact layout the active tab and the toolbar segments on either
|
||||
side share one theme color, so the toolbar is the same color as the tab
|
||||
strip and inactive tabs are drawn lighter, as Dolphin does.
|
||||
- Helium uses the GTK theme (Settings → Appearance → Theme: GTK) with "Use
|
||||
system title bar and borders" off, so the tab strip doubles as the title
|
||||
bar. Its colors come from Breeze GTK, which `kde-gtk-config` syncs from
|
||||
the scheme; there is no Helium theme to generate.
|
||||
- With the system title bar off, Helium draws the window buttons through
|
||||
GTK. `kde-gtk-config` renders the KWin buttons into
|
||||
`~/.config/gtk-3.0/window_decorations.css`, but hands that file to GTK apps
|
||||
through a GTK module that Helium doesn't load, so Helium would show Breeze
|
||||
GTK's own round buttons instead. `apply.sh` imports the file from `gtk.css`
|
||||
so Helium picks it up too.
|
||||
- In the compact layout, the address bar takes GTK's text field color and the
|
||||
segment with the extension and window buttons takes the window color, which
|
||||
Chromium resolves to the darker view color. `.config/gtk-3.0/chromium.css`
|
||||
gives both the title bar color, and `apply.sh` imports it from `gtk.css`.
|
||||
Chromium adds a `chromium` class to every GTK node it reads colors from, so
|
||||
the rules reach Helium and no other GTK app.
|
||||
- Chromium tags its output as sRGB and KWin shows it with a gamma 2.2 curve,
|
||||
which lifts dark grays (40 becomes 44). `build.py` writes pre-compensated
|
||||
values for Helium and T3 Code (both Chromium), so the theme files say 35
|
||||
where the screen shows 40.
|
||||
- Under Settings → Appearance the theme must be Classic, not GTK or QT.
|
||||
which lifts dark grays (40 becomes 44). T3 Code and VS Code get
|
||||
pre-compensated colors from `build.py`; Helium instead runs with
|
||||
`--disable-features=WaylandWpColorManagerV1`, so its surfaces go untagged
|
||||
and show the GTK colors as they are.
|
||||
|
||||
## When the colors don't show up
|
||||
|
||||
|
||||
+16
-1
@@ -21,6 +21,21 @@ plasma-apply-lookandfeel --apply dev.trivk.darwinbreeze.dark
|
||||
plasma-apply-colorscheme BreezeClassic >/dev/null
|
||||
plasma-apply-colorscheme DarwinBreezeDark >/dev/null
|
||||
|
||||
# kde-gtk-config writes gtk.css; add our imports to it.
|
||||
gtk_import() {
|
||||
local css="${XDG_CONFIG_HOME:-$HOME/.config}/$1/gtk.css"
|
||||
if [ -e "$css" ] && ! grep -qF "'$2'" "$css"; then
|
||||
sed -i "\$a @import '$2';" "$css"
|
||||
fi
|
||||
}
|
||||
# kde-gtk-config gives GTK apps the KWin title buttons through a GTK module,
|
||||
# which Helium doesn't load, so it would fall back to Breeze GTK's own
|
||||
# buttons. Importing the same CSS from gtk.css reaches Helium too.
|
||||
gtk_import gtk-3.0 window_decorations.css
|
||||
gtk_import gtk-4.0 window_decorations.css
|
||||
# Helium's tab strip colors (see chromium.css).
|
||||
gtk_import gtk-3.0 chromium.css
|
||||
|
||||
# Drop the line under the title bar so it blends into the toolbar.
|
||||
kwriteconfig6 --file breezerc --group Windeco --key DrawTitleBarSeparator false
|
||||
|
||||
@@ -45,5 +60,5 @@ fi
|
||||
|
||||
echo "Applied Darwin Breeze"
|
||||
if pgrep -x helium >/dev/null; then
|
||||
echo "Restart Helium to pick up its theme"
|
||||
echo "Restart Helium to pick up the new colors"
|
||||
fi
|
||||
+3
-53
@@ -4,7 +4,6 @@
|
||||
.local/share/color-schemes/DarwinBreezeDark.colors is the only place colors
|
||||
are defined. This script derives from it:
|
||||
|
||||
../helium/.local/share/helium-themes/darwinbreeze/manifest.json
|
||||
t3/darwin-breeze.json (published to T3 Code by apply.sh)
|
||||
telegram/DarwinBreezeDark.tdesktop-theme (not committed; imported into Telegram by hand)
|
||||
vscode/ (packed into vscode/darwin-breeze.vsix, installed by apply.sh)
|
||||
@@ -24,7 +23,6 @@ from pathlib import Path
|
||||
HERE = Path(__file__).resolve().parent
|
||||
PKG = HERE
|
||||
SCHEME = PKG / ".local/share/color-schemes/DarwinBreezeDark.colors"
|
||||
HELIUM = PKG.parent / "helium/.local/share/helium-themes/darwinbreeze"
|
||||
T3 = HERE / "t3/darwin-breeze.json"
|
||||
# Telegram Desktop's built-in night theme, used as the base for every key the
|
||||
# scheme has no role for: the colors file from telegramdesktop/tdesktop at
|
||||
@@ -54,10 +52,6 @@ CYAN = (100, 210, 255)
|
||||
# Apple systemYellow; search highlights in T3 Code.
|
||||
YELLOW = (255, 255, 0)
|
||||
|
||||
# Breeze draws inactive tabs this far from the window color towards the text
|
||||
# color (measured in Dolphin: 40 -> 62 with text 222).
|
||||
INACTIVE_TAB_MIX = 0.12
|
||||
|
||||
|
||||
def load() -> ColorFn:
|
||||
cp = configparser.ConfigParser(interpolation=None, strict=False)
|
||||
@@ -84,7 +78,8 @@ def kwin_compensate(c: Sequence[int]) -> list[int]:
|
||||
|
||||
Chromium tags its surfaces as sRGB, KWin shows them with a gamma 2.2
|
||||
curve, so dark grays come out lighter (40 -> 44). Encoding the target
|
||||
with the inverse makes Helium land on the same values as native apps.
|
||||
with the inverse makes Chromium apps land on the same values as native
|
||||
apps.
|
||||
"""
|
||||
|
||||
def ch(v: int) -> int:
|
||||
@@ -95,40 +90,6 @@ def kwin_compensate(c: Sequence[int]) -> list[int]:
|
||||
return [ch(v) for v in c]
|
||||
|
||||
|
||||
def helium(color: ColorFn) -> dict[str, list[int]]:
|
||||
bar = color("Header", "BackgroundNormal")
|
||||
text = color("Window", "ForegroundNormal")
|
||||
view = color("View", "BackgroundNormal")
|
||||
view_text = color("View", "ForegroundNormal")
|
||||
inactive_tab = mix(bar, text, INACTIVE_TAB_MIX)
|
||||
|
||||
# In Helium's compact layout the active tab and the toolbar segments on
|
||||
# either side share the toolbar color, so toolbar and frame must match
|
||||
# for the strip to read as one bar. Inactive tabs get the lighter Breeze
|
||||
# tab color, the way Dolphin draws them.
|
||||
colors = {
|
||||
"frame": bar,
|
||||
"frame_inactive": bar,
|
||||
"frame_incognito": bar,
|
||||
"frame_incognito_inactive": bar,
|
||||
"toolbar": bar,
|
||||
"background_tab": inactive_tab,
|
||||
"background_tab_inactive": inactive_tab,
|
||||
"tab_text": text,
|
||||
"tab_background_text": text,
|
||||
"tab_background_text_inactive": color("Window", "ForegroundInactive"),
|
||||
"toolbar_text": text,
|
||||
"toolbar_button_icon": text,
|
||||
"bookmark_text": text,
|
||||
"omnibox_background": view,
|
||||
"omnibox_text": view_text,
|
||||
"ntp_background": view,
|
||||
"ntp_text": view_text,
|
||||
"ntp_link": color("View", "ForegroundLink"),
|
||||
}
|
||||
return {k: kwin_compensate(v) for k, v in colors.items()}
|
||||
|
||||
|
||||
def ansi(color: ColorFn) -> list[Color]:
|
||||
"""The 16 colors for the VS Code terminal."""
|
||||
bg = color("View", "BackgroundNormal")
|
||||
@@ -530,7 +491,7 @@ def vscode(color: ColorFn) -> dict[str, str]:
|
||||
|
||||
colors = {k: pins.get(k) or recolor(c) for k, c in base.items()}
|
||||
colors.update(pins)
|
||||
# Electron is Chromium, so it needs the same KWin compensation as Helium.
|
||||
# Electron is Chromium, so it needs the KWin compensation.
|
||||
return {k: hexc(kwin_compensate(c[:3]) + list(c[3:])) for k, c in sorted(colors.items())}
|
||||
|
||||
|
||||
@@ -638,17 +599,6 @@ def write(path: Path, data: str | bytes) -> bool:
|
||||
|
||||
def main() -> None:
|
||||
color = load()
|
||||
manifest = {
|
||||
"manifest_version": 3,
|
||||
"name": "Darwin Breeze",
|
||||
"version": "1.0",
|
||||
"description": f"Generated by kde/theme/build.py from {SCHEME.name}",
|
||||
"theme": {"colors": helium(color)},
|
||||
}
|
||||
if write(HELIUM / "manifest.json", json.dumps(manifest, indent=2) + "\n"):
|
||||
# Helium would keep showing the old colors from its cache.
|
||||
(HELIUM / "Cached Theme.pak").unlink(missing_ok=True)
|
||||
|
||||
theme = {"version": 1, "name": "Darwin Breeze", "appearance": "dark", "colors": t3(color)}
|
||||
write(T3, json.dumps(theme, indent=2) + "\n")
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
# Patch netbird-ui's tray icons to Breeze proportions.
|
||||
# Runs as root; the pacman hook re-runs it after every netbird-ui install/upgrade.
|
||||
set -euo pipefail
|
||||
here=$(cd "$(dirname "$0")" && pwd)
|
||||
ROOT=${ROOT:-} # for dry-run testing only
|
||||
bin=$ROOT/usr/bin/netbird-ui
|
||||
[[ -f $bin ]] || exit 0
|
||||
|
||||
# Still the file the package installed: keep it as the original for restore.sh
|
||||
sum=$(zcat "$ROOT"/var/lib/pacman/local/netbird-ui*/mtree 2>/dev/null \
|
||||
| grep -F './usr/bin/netbird-ui ' | grep -o 'sha256digest=[0-9a-f]*' | cut -d= -f2 || true)
|
||||
if [[ -n $sum && $(sha256sum <"$bin" | cut -d' ' -f1) == "$sum" ]]; then
|
||||
install -Dm755 "$bin" "$here/orig/netbird-ui"
|
||||
fi
|
||||
python3 -I "$here/patch.py" "$bin"
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
# Install the netbird-ui tray icon patch and its pacman hook. Usage: sudo ./install.sh
|
||||
set -euo pipefail
|
||||
here=$(cd "$(dirname "$0")" && pwd)
|
||||
ROOT=${ROOT:-} # for dry-run testing only
|
||||
[[ $EUID -eq 0 || -n $ROOT ]] || { echo "Must be run with sudo"; exit 1; }
|
||||
dest=$ROOT/usr/local/share/netbird-breeze-icons
|
||||
|
||||
install -Dm755 "$here/patch.py" "$dest/patch.py"
|
||||
install -m755 "$here/apply.sh" "$dest/apply.sh"
|
||||
install -Dm644 "$here/netbird-breeze-icons.hook" "$ROOT/etc/pacman.d/hooks/netbird-breeze-icons.hook"
|
||||
ROOT=$ROOT "$dest/apply.sh"
|
||||
|
||||
echo "Done. Restart the NetBird UI (without sudo):"
|
||||
echo " pkill -x netbird-ui; setsid -f netbird-ui --daemon-addr unix:///var/run/netbird/main.sock >/dev/null 2>&1"
|
||||
@@ -0,0 +1,11 @@
|
||||
[Trigger]
|
||||
Operation = Install
|
||||
Operation = Upgrade
|
||||
Type = Package
|
||||
Target = netbird-ui
|
||||
Target = netbird-ui-bin
|
||||
|
||||
[Action]
|
||||
Description = Patching NetBird tray icons to match Breeze...
|
||||
When = PostTransaction
|
||||
Exec = /usr/local/share/netbird-breeze-icons/apply.sh
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Shrink and recolor the tray icons embedded in the netbird-ui binary.
|
||||
|
||||
NetBird sends its tray icon as a pixmap, so an icon theme can't replace it.
|
||||
This rewrites the 48x48 monochrome PNGs inside the binary in place: the
|
||||
glyph is scaled to SCALE so it gets the padding of a Breeze status icon,
|
||||
and the white variants take the panel's text color. Each new PNG must fit
|
||||
in the bytes of the old one; the rest is zero-filled, which Go's PNG
|
||||
decoder never reads because it stops at IEND.
|
||||
|
||||
Usage: patch.py BINARY [--check]
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
from pathlib import Path
|
||||
import struct
|
||||
import sys
|
||||
import tempfile
|
||||
import zlib
|
||||
|
||||
SIZE = 48
|
||||
SCALE = 0.8
|
||||
# DarwinBreezeDark ForegroundNormal, as the other tray icons are drawn
|
||||
LIGHT = (222, 222, 222)
|
||||
# A glyph narrower than this already has padding (already patched)
|
||||
MAX_PADDED_WIDTH = round(SIZE * 0.9)
|
||||
SIG = b"\x89PNG\r\n\x1a\n"
|
||||
|
||||
Pixels = list[list[float]] # rows of premultiplied RGBA floats
|
||||
|
||||
|
||||
def decode(png: bytes) -> tuple[int, int, bytes] | None:
|
||||
"""Return (width, height, RGBA rows) for an 8-bit RGBA PNG, else None."""
|
||||
pos, idat, ihdr = 8, b"", b""
|
||||
while pos < len(png):
|
||||
(length,) = struct.unpack(">I", png[pos:pos + 4])
|
||||
kind, body = png[pos + 4:pos + 8], png[pos + 8:pos + 8 + length]
|
||||
if kind == b"IHDR":
|
||||
ihdr = body
|
||||
elif kind == b"IDAT":
|
||||
idat += body
|
||||
elif kind == b"IEND":
|
||||
break
|
||||
pos += 12 + length
|
||||
w, h, depth, color, _, _, interlace = struct.unpack(">IIBBBBB", ihdr)
|
||||
if (depth, color, interlace) != (8, 6, 0):
|
||||
return None
|
||||
raw, stride, out = zlib.decompress(idat), w * 4, bytearray()
|
||||
prev = bytearray(stride)
|
||||
for y in range(h):
|
||||
ftype = raw[y * (stride + 1)]
|
||||
line = bytearray(raw[y * (stride + 1) + 1:(y + 1) * (stride + 1)])
|
||||
for i in range(stride):
|
||||
a = line[i - 4] if i >= 4 else 0
|
||||
b = prev[i]
|
||||
c = prev[i - 4] if i >= 4 else 0
|
||||
if ftype == 1:
|
||||
line[i] = (line[i] + a) & 0xFF
|
||||
elif ftype == 2:
|
||||
line[i] = (line[i] + b) & 0xFF
|
||||
elif ftype == 3:
|
||||
line[i] = (line[i] + (a + b) // 2) & 0xFF
|
||||
elif ftype == 4:
|
||||
p = a + b - c
|
||||
pa, pb, pc = abs(p - a), abs(p - b), abs(p - c)
|
||||
pred = a if pa <= pb and pa <= pc else b if pb <= pc else c
|
||||
line[i] = (line[i] + pred) & 0xFF
|
||||
out += line
|
||||
prev = line
|
||||
return w, h, bytes(out)
|
||||
|
||||
|
||||
def encode(w: int, h: int, rgba: bytes) -> bytes:
|
||||
def chunk(kind: bytes, body: bytes) -> bytes:
|
||||
crc = zlib.crc32(kind + body)
|
||||
return struct.pack(">I", len(body)) + kind + body + struct.pack(">I", crc)
|
||||
|
||||
raw = b"".join(b"\0" + rgba[y * w * 4:(y + 1) * w * 4] for y in range(h))
|
||||
return (SIG + chunk(b"IHDR", struct.pack(">IIBBBBB", w, h, 8, 6, 0, 0, 0))
|
||||
+ chunk(b"IDAT", zlib.compress(raw, 9)) + chunk(b"IEND", b""))
|
||||
|
||||
|
||||
def glyph_width(rgba: bytes) -> int:
|
||||
xs = [i // 4 % SIZE for i in range(3, len(rgba), 4) if rgba[i] > 16]
|
||||
return max(xs) - min(xs) + 1 if xs else 0
|
||||
|
||||
|
||||
def is_light(rgba: bytes) -> bool | None:
|
||||
"""True for a white glyph, False for black, None if not monochrome."""
|
||||
lum = [rgba[i - 3] for i in range(3, len(rgba), 4) if rgba[i] > 200]
|
||||
if not lum or any(abs(rgba[i - 3] - rgba[i - 2]) > 8 for i in range(3, len(rgba), 4)
|
||||
if rgba[i] > 200):
|
||||
return None
|
||||
if all(v > 230 for v in lum):
|
||||
return True
|
||||
if all(v < 25 for v in lum):
|
||||
return False
|
||||
return None
|
||||
|
||||
|
||||
def shrink(rgba: bytes, light: bool) -> bytes:
|
||||
"""Box-filter the image to SCALE, centered on a SIZE canvas."""
|
||||
src: Pixels = []
|
||||
for y in range(SIZE):
|
||||
row: list[float] = []
|
||||
for x in range(SIZE):
|
||||
r, g, b, a = rgba[(y * SIZE + x) * 4:(y * SIZE + x) * 4 + 4]
|
||||
row += [r * a, g * a, b * a, a]
|
||||
src.append(row)
|
||||
inner = SIZE * SCALE
|
||||
off = (SIZE - inner) / 2
|
||||
step = 1 / SCALE
|
||||
out = bytearray(SIZE * SIZE * 4)
|
||||
|
||||
def spans(o: int) -> list[tuple[int, float]]:
|
||||
lo = (o - off) * step
|
||||
hi = lo + step
|
||||
res = []
|
||||
for s in range(max(0, int(lo)), min(SIZE, int(hi) + 1)):
|
||||
cover = min(hi, s + 1) - max(lo, s)
|
||||
if cover > 0:
|
||||
res.append((s, cover))
|
||||
return res
|
||||
|
||||
for oy in range(SIZE):
|
||||
ys = spans(oy)
|
||||
for ox in range(SIZE):
|
||||
acc = [0.0] * 4
|
||||
for sy, wy in ys:
|
||||
for sx, wx in spans(ox):
|
||||
k = wy * wx
|
||||
for c in range(4):
|
||||
acc[c] += src[sy][sx * 4 + c] * k
|
||||
area = step * step
|
||||
a = acc[3] / area
|
||||
if a < 0.5:
|
||||
continue
|
||||
color = LIGHT if light else tuple(round(acc[c] / acc[3]) for c in range(3))
|
||||
out[(oy * SIZE + ox) * 4:(oy * SIZE + ox) * 4 + 4] = bytes(
|
||||
[*color, min(255, round(a))])
|
||||
return bytes(out)
|
||||
|
||||
|
||||
def patch(data: bytearray) -> int:
|
||||
count, pos = 0, 0
|
||||
while (pos := data.find(SIG, pos)) >= 0:
|
||||
end = data.find(b"IEND", pos) + 8
|
||||
old = bytes(data[pos:end])
|
||||
img = decode(old) if old[16:24] == struct.pack(">II", SIZE, SIZE) else None
|
||||
if img is not None:
|
||||
light = is_light(img[2])
|
||||
if light is not None and glyph_width(img[2]) > MAX_PADDED_WIDTH:
|
||||
new = encode(SIZE, SIZE, shrink(img[2], light))
|
||||
if len(new) > len(old):
|
||||
sys.exit(f"Patched icon at {pos} is larger than the original")
|
||||
data[pos:end] = new + bytes(len(old) - len(new))
|
||||
count += 1
|
||||
pos = end
|
||||
return count
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
||||
parser.add_argument("binary", type=Path)
|
||||
parser.add_argument("--check", action="store_true",
|
||||
help="only print how many icons would be patched")
|
||||
args = parser.parse_args()
|
||||
data = bytearray(args.binary.read_bytes())
|
||||
count = patch(data)
|
||||
print(f"{args.binary}: {count} tray icons {'to patch' if args.check else 'patched'}")
|
||||
if args.check or not count:
|
||||
return
|
||||
mode = args.binary.stat().st_mode
|
||||
fd, tmp = tempfile.mkstemp(dir=args.binary.parent, prefix=".netbird-ui.")
|
||||
with os.fdopen(fd, "wb") as f:
|
||||
f.write(data)
|
||||
os.chmod(tmp, mode & 0o7777)
|
||||
os.replace(tmp, args.binary)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
# Put the original netbird-ui back and remove the hook. Usage: sudo ./restore.sh
|
||||
set -euo pipefail
|
||||
ROOT=${ROOT:-} # for dry-run testing only
|
||||
[[ $EUID -eq 0 || -n $ROOT ]] || { echo "Must be run with sudo"; exit 1; }
|
||||
dest=$ROOT/usr/local/share/netbird-breeze-icons
|
||||
[[ -f $dest/orig/netbird-ui ]] || { echo "No original binary in $dest/orig"; exit 1; }
|
||||
install -m755 "$dest/orig/netbird-ui" "$ROOT/usr/bin/netbird-ui"
|
||||
rm -f "$ROOT/etc/pacman.d/hooks/netbird-breeze-icons.hook"
|
||||
rm -rf "$dest"
|
||||
echo "Restored. Restart the NetBird UI (without sudo):"
|
||||
echo " pkill -x netbird-ui; setsid -f netbird-ui --daemon-addr unix:///var/run/netbird/main.sock >/dev/null 2>&1"
|
||||
@@ -31,6 +31,29 @@ systemctl --user restart plasma-plasmashell
|
||||
- On KDE Wayland don't start fcitx5 with `fcitx5 -d`; use
|
||||
`restart-fcitx5.sh` so KWin launches it.
|
||||
|
||||
## NetBird (netbird-ui)
|
||||
|
||||
Scales NetBird's tray icons down to 80% so they get the padding of Breeze
|
||||
status icons, and draws the white ones in the panel's text color
|
||||
(`#dedede`) instead of pure white.
|
||||
|
||||
```sh
|
||||
sudo ~/.local/share/netbird-breeze-icons/install.sh
|
||||
pkill -x netbird-ui; setsid -f netbird-ui --daemon-addr unix:///var/run/netbird/main.sock >/dev/null 2>&1
|
||||
```
|
||||
|
||||
- NetBird sends the tray icon as raw pixels, not an icon name, so an icon
|
||||
theme can't replace it. `patch.py` rewrites the 48x48 PNGs embedded in
|
||||
`/usr/bin/netbird-ui` in place instead; each new PNG fits in the bytes
|
||||
of the old one.
|
||||
- `install.sh` copies `patch.py` and `apply.sh` to
|
||||
`/usr/local/share/netbird-breeze-icons/` and installs the pacman hook
|
||||
`/etc/pacman.d/hooks/netbird-breeze-icons.hook` to re-patch the binary
|
||||
after every `netbird-ui`/`netbird-ui-bin` upgrade.
|
||||
- The original binary is kept in `/usr/local/share/netbird-breeze-icons/orig/`;
|
||||
`sudo ~/.local/share/netbird-breeze-icons/restore.sh` puts it back and
|
||||
removes the hook.
|
||||
|
||||
## qBittorrent
|
||||
|
||||
`qbittorrent-tray-mono.svg` is qBittorrent's monochrome tray icon scaled
|
||||
|
||||
+1
-7
@@ -6,16 +6,10 @@ From the repository root, install all macOS packages:
|
||||
(cd mac && stow -t "$HOME" */)
|
||||
```
|
||||
|
||||
Or choose individual packages:
|
||||
Install the package:
|
||||
|
||||
```sh
|
||||
stow -d mac -t "$HOME" ghostty
|
||||
stow -d mac -t "$HOME" fastfetch
|
||||
```
|
||||
|
||||
- `ghostty`: JetBrainsMono Nerd Font and Ghostty's bundled SpaceGray Eighties theme.
|
||||
- `fastfetch`: the original configuration, with a `kitty-direct` image logo.
|
||||
Its source PNG is included in `fastfetch/.config/fastfetch/`.
|
||||
|
||||
These packages are independent. Choose either `mac/fastfetch` or
|
||||
`kde/fastfetch`; both own `~/.config/fastfetch/`.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 138 KiB |
@@ -1,80 +0,0 @@
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/master/doc/json_schema.json",
|
||||
"display": {
|
||||
"key": {
|
||||
"width": 10
|
||||
},
|
||||
"size": {
|
||||
"binaryPrefix": "jedec"
|
||||
},
|
||||
"separator": ""
|
||||
},
|
||||
"logo": {
|
||||
"type": "kitty-direct",
|
||||
"source": "~/.config/fastfetch/albedo.png",
|
||||
"width": 20,
|
||||
"height": 10
|
||||
},
|
||||
"modules": [
|
||||
"break",
|
||||
{
|
||||
"type": "os",
|
||||
"key": "os",
|
||||
"keyColor": "yellow",
|
||||
"format": "{name}"
|
||||
},
|
||||
{
|
||||
"type": "kernel",
|
||||
"key": "ker",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "packages",
|
||||
"key": "pkgs",
|
||||
"keyColor": "cyan"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"key": "sh",
|
||||
"keyColor": "blue",
|
||||
"format": "{pretty-name}"
|
||||
},
|
||||
{
|
||||
"type": "wm",
|
||||
"key": "wm",
|
||||
"keyColor": "red",
|
||||
"format": "{pretty-name}"
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
"key": "up",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "cpu",
|
||||
"key": "cpu",
|
||||
"keyColor": "red",
|
||||
"format": "{name}"
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "ram",
|
||||
"keyColor": "yellow",
|
||||
"format": "{used} / {total}"
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": "disk",
|
||||
"keyColor": "cyan",
|
||||
"folders": [
|
||||
"/"
|
||||
],
|
||||
"format": "{size-used} / {size-total}"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "\u001b[33m \u001b[32m \u001b[34m \u001b[31m \u001b[36m \u001b[35m \u001b[37m \u001b[97m"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in new issue
Block a user