feat(darwin-breeze): unify theme colors across KDE, Helium, T3 Code and Ghostty
Move the Darwin Breeze Dark color scheme and global theme into a stow package. build.py generates the Helium, T3 Code and Ghostty themes from DarwinBreezeDark.colors, and apply.sh rebuilds and applies them, so the colors are edited in one place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d215693df4
commit
75b1383edf
14 files changed
+798
-1
No files matched your search
@@ -30,6 +30,18 @@ git -C $HOME clone https://github.com/vokhactri/.dotfiles.git && cd $HOME/.dotfi
|
|||||||
exec zsh
|
exec zsh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `darwin-breeze` + `helium` (theme and colors)
|
||||||
|
|
||||||
|
The Darwin Breeze Dark KDE color scheme and global theme, and the Helium, T3
|
||||||
|
Code and Ghostty themes generated from it. After stowing, apply it once:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./darwin-breeze/apply.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
To change colors, edit `DarwinBreezeDark.colors` and run `apply.sh` again; see
|
||||||
|
[`darwin-breeze/README.md`](darwin-breeze/README.md).
|
||||||
|
|
||||||
### `tray-icons` (tray icons that match Breeze)
|
### `tray-icons` (tray icons that match Breeze)
|
||||||
|
|
||||||
Some icons need an extra step after `stow tray-icons` (a root step for
|
Some icons need an extra step after `stow tray-icons` (a root step for
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Generated by darwin-breeze/build.py from DarwinBreezeDark.colors
|
||||||
|
background = #1e1e1e
|
||||||
|
foreground = #dddddd
|
||||||
|
cursor-color = #007aff
|
||||||
|
cursor-text = #ffffff
|
||||||
|
selection-background = #007aff
|
||||||
|
selection-foreground = #ffffff
|
||||||
|
palette = 0=#3b3b3b
|
||||||
|
palette = 1=#ff4a4c
|
||||||
|
palette = 2=#30d158
|
||||||
|
palette = 3=#ff9230
|
||||||
|
palette = 4=#419cff
|
||||||
|
palette = 5=#bf5af2
|
||||||
|
palette = 6=#64d2ff
|
||||||
|
palette = 7=#dddddd
|
||||||
|
palette = 8=#747474
|
||||||
|
palette = 9=#ff7779
|
||||||
|
palette = 10=#64dc82
|
||||||
|
palette = 11=#ffad64
|
||||||
|
palette = 12=#70b5ff
|
||||||
|
palette = 13=#cf83f5
|
||||||
|
palette = 14=#8bddff
|
||||||
|
palette = 15=#f1f1f1
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Helium caches the built theme next to the manifest.
|
||||||
|
Cached Theme.pak
|
||||||
|
__pycache__/
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
# macOS-inspired colors for Breeze (dark variant).
|
||||||
|
# Header and Window share one color so the title bar merges into the toolbar.
|
||||||
|
|
||||||
|
[ColorEffects:Disabled]
|
||||||
|
Color=56,56,56
|
||||||
|
ColorAmount=0
|
||||||
|
ColorEffect=0
|
||||||
|
ContrastAmount=0.65
|
||||||
|
ContrastEffect=1
|
||||||
|
IntensityAmount=0.1
|
||||||
|
IntensityEffect=2
|
||||||
|
|
||||||
|
[ColorEffects:Inactive]
|
||||||
|
ChangeSelectionColor=true
|
||||||
|
Color=112,111,110
|
||||||
|
ColorAmount=0.025
|
||||||
|
ColorEffect=2
|
||||||
|
ContrastAmount=0.1
|
||||||
|
ContrastEffect=2
|
||||||
|
Enable=false
|
||||||
|
IntensityAmount=0
|
||||||
|
IntensityEffect=0
|
||||||
|
|
||||||
|
[Colors:Button]
|
||||||
|
BackgroundAlternate=109,109,109
|
||||||
|
BackgroundNormal=93,93,93
|
||||||
|
DecorationFocus=0,122,255
|
||||||
|
DecorationHover=0,122,255
|
||||||
|
ForegroundActive=65,156,255
|
||||||
|
ForegroundInactive=154,154,154
|
||||||
|
ForegroundLink=65,156,255
|
||||||
|
ForegroundNegative=255,74,76
|
||||||
|
ForegroundNeutral=255,146,48
|
||||||
|
ForegroundNormal=230,230,230
|
||||||
|
ForegroundPositive=48,209,88
|
||||||
|
ForegroundVisited=191,90,242
|
||||||
|
|
||||||
|
[Colors:Complementary]
|
||||||
|
BackgroundAlternate=40,40,40
|
||||||
|
BackgroundNormal=30,30,30
|
||||||
|
DecorationFocus=0,122,255
|
||||||
|
DecorationHover=0,122,255
|
||||||
|
ForegroundActive=65,156,255
|
||||||
|
ForegroundInactive=154,154,154
|
||||||
|
ForegroundLink=65,156,255
|
||||||
|
ForegroundNegative=255,74,76
|
||||||
|
ForegroundNeutral=255,146,48
|
||||||
|
ForegroundNormal=221,221,221
|
||||||
|
ForegroundPositive=48,209,88
|
||||||
|
ForegroundVisited=191,90,242
|
||||||
|
|
||||||
|
[Colors:Header]
|
||||||
|
BackgroundAlternate=40,40,40
|
||||||
|
BackgroundNormal=40,40,40
|
||||||
|
DecorationFocus=0,122,255
|
||||||
|
DecorationHover=0,122,255
|
||||||
|
ForegroundActive=65,156,255
|
||||||
|
ForegroundInactive=154,154,154
|
||||||
|
ForegroundLink=65,156,255
|
||||||
|
ForegroundNegative=255,74,76
|
||||||
|
ForegroundNeutral=255,146,48
|
||||||
|
ForegroundNormal=222,222,222
|
||||||
|
ForegroundPositive=48,209,88
|
||||||
|
ForegroundVisited=191,90,242
|
||||||
|
|
||||||
|
[Colors:Header][Inactive]
|
||||||
|
BackgroundAlternate=36,36,36
|
||||||
|
BackgroundNormal=36,36,36
|
||||||
|
DecorationFocus=0,122,255
|
||||||
|
DecorationHover=0,122,255
|
||||||
|
ForegroundActive=65,156,255
|
||||||
|
ForegroundInactive=128,128,128
|
||||||
|
ForegroundLink=65,156,255
|
||||||
|
ForegroundNegative=255,74,76
|
||||||
|
ForegroundNeutral=255,146,48
|
||||||
|
ForegroundNormal=154,154,154
|
||||||
|
ForegroundPositive=48,209,88
|
||||||
|
ForegroundVisited=191,90,242
|
||||||
|
|
||||||
|
[Colors:Selection]
|
||||||
|
BackgroundAlternate=25,135,255
|
||||||
|
BackgroundNormal=0,122,255
|
||||||
|
DecorationFocus=0,122,255
|
||||||
|
DecorationHover=0,122,255
|
||||||
|
ForegroundActive=255,255,255
|
||||||
|
ForegroundInactive=222,222,222
|
||||||
|
ForegroundLink=255,255,255
|
||||||
|
ForegroundNegative=255,200,200
|
||||||
|
ForegroundNeutral=255,220,180
|
||||||
|
ForegroundNormal=255,255,255
|
||||||
|
ForegroundPositive=200,255,210
|
||||||
|
ForegroundVisited=230,210,255
|
||||||
|
|
||||||
|
# macOS turns the selection gray when the window loses focus.
|
||||||
|
[Colors:Selection][Inactive]
|
||||||
|
BackgroundAlternate=70,70,70
|
||||||
|
BackgroundNormal=70,70,70
|
||||||
|
DecorationFocus=0,122,255
|
||||||
|
DecorationHover=0,122,255
|
||||||
|
ForegroundActive=255,255,255
|
||||||
|
ForegroundInactive=222,222,222
|
||||||
|
ForegroundLink=255,255,255
|
||||||
|
ForegroundNegative=255,74,76
|
||||||
|
ForegroundNeutral=255,146,48
|
||||||
|
ForegroundNormal=255,255,255
|
||||||
|
ForegroundPositive=48,209,88
|
||||||
|
ForegroundVisited=191,90,242
|
||||||
|
|
||||||
|
[Colors:Tooltip]
|
||||||
|
BackgroundAlternate=46,46,46
|
||||||
|
BackgroundNormal=40,40,40
|
||||||
|
DecorationFocus=0,122,255
|
||||||
|
DecorationHover=0,122,255
|
||||||
|
ForegroundActive=65,156,255
|
||||||
|
ForegroundInactive=154,154,154
|
||||||
|
ForegroundLink=65,156,255
|
||||||
|
ForegroundNegative=255,74,76
|
||||||
|
ForegroundNeutral=255,146,48
|
||||||
|
ForegroundNormal=222,222,222
|
||||||
|
ForegroundPositive=48,209,88
|
||||||
|
ForegroundVisited=191,90,242
|
||||||
|
|
||||||
|
[Colors:View]
|
||||||
|
BackgroundAlternate=37,37,37
|
||||||
|
BackgroundNormal=30,30,30
|
||||||
|
DecorationFocus=0,122,255
|
||||||
|
DecorationHover=0,122,255
|
||||||
|
ForegroundActive=65,156,255
|
||||||
|
ForegroundInactive=154,154,154
|
||||||
|
ForegroundLink=65,156,255
|
||||||
|
ForegroundNegative=255,74,76
|
||||||
|
ForegroundNeutral=255,146,48
|
||||||
|
ForegroundNormal=221,221,221
|
||||||
|
ForegroundPositive=48,209,88
|
||||||
|
ForegroundVisited=191,90,242
|
||||||
|
|
||||||
|
[Colors:Window]
|
||||||
|
BackgroundAlternate=46,46,46
|
||||||
|
BackgroundNormal=40,40,40
|
||||||
|
DecorationFocus=0,122,255
|
||||||
|
DecorationHover=0,122,255
|
||||||
|
ForegroundActive=65,156,255
|
||||||
|
ForegroundInactive=154,154,154
|
||||||
|
ForegroundLink=65,156,255
|
||||||
|
ForegroundNegative=255,74,76
|
||||||
|
ForegroundNeutral=255,146,48
|
||||||
|
ForegroundNormal=222,222,222
|
||||||
|
ForegroundPositive=48,209,88
|
||||||
|
ForegroundVisited=191,90,242
|
||||||
|
|
||||||
|
[General]
|
||||||
|
ColorScheme=DarwinBreezeDark
|
||||||
|
Name=Darwin Breeze Dark
|
||||||
|
shadeSortColumn=true
|
||||||
|
|
||||||
|
[KDE]
|
||||||
|
contrast=4
|
||||||
|
|
||||||
|
[WM]
|
||||||
|
activeBackground=40,40,40
|
||||||
|
activeBlend=40,40,40
|
||||||
|
activeForeground=222,222,222
|
||||||
|
inactiveBackground=36,36,36
|
||||||
|
inactiveBlend=36,36,36
|
||||||
|
inactiveForeground=154,154,154
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"manifest_version": 3,
|
||||||
|
"name": "Darwin Breeze",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": "Generated by darwin-breeze/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
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
[kdeglobals][KDE]
|
||||||
|
widgetStyle=Breeze
|
||||||
|
|
||||||
|
[kdeglobals][General]
|
||||||
|
ColorScheme=DarwinBreezeDark
|
||||||
|
|
||||||
|
[kdeglobals][Icons]
|
||||||
|
Theme=breeze-dark
|
||||||
|
|
||||||
|
[plasmarc][Theme]
|
||||||
|
name=default
|
||||||
|
|
||||||
|
[kcminputrc][Mouse]
|
||||||
|
cursorTheme=breeze_cursors
|
||||||
|
|
||||||
|
[kwinrc][WindowSwitcher]
|
||||||
|
LayoutName=org.kde.breeze.desktop
|
||||||
|
|
||||||
|
[kwinrc][DesktopSwitcher]
|
||||||
|
LayoutName=org.kde.breeze.desktop
|
||||||
|
|
||||||
|
[kwinrc][org.kde.kdecoration2]
|
||||||
|
library=org.kde.breeze
|
||||||
|
theme=Breeze
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"KPackageStructure": "Plasma/LookAndFeel",
|
||||||
|
"KPlugin": {
|
||||||
|
"Authors": [
|
||||||
|
{
|
||||||
|
"Name": "trivk"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Category": "",
|
||||||
|
"Description": "Breeze in macOS-inspired colors (dark)",
|
||||||
|
"Id": "dev.trivk.darwinbreeze.dark",
|
||||||
|
"License": "GPL-2.0-or-later",
|
||||||
|
"Name": "Darwin Breeze Dark",
|
||||||
|
"Version": "1.0"
|
||||||
|
},
|
||||||
|
"X-Plasma-APIVersion": "2"
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Build and apply scripts stay in the repo; only the dotfiles get linked.
|
||||||
|
^/README.*
|
||||||
|
^/apply\.sh
|
||||||
|
^/build\.py
|
||||||
|
__pycache__
|
||||||
|
^/\.gitignore
|
||||||
|
^/t3
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# Darwin Breeze
|
||||||
|
|
||||||
|
Breeze for KDE Plasma 6 in the macOS dark system colors, with Helium, T3 Code
|
||||||
|
and Ghostty themed from the same colors.
|
||||||
|
|
||||||
|
Only the colors change. Breeze still draws the widgets and the title bar, and
|
||||||
|
the window buttons stay on the right.
|
||||||
|
|
||||||
|
- Selection and focus rings use the macOS blue, `#007AFF`.
|
||||||
|
- The title bar has the same color as the toolbar below it, so the two read as
|
||||||
|
one strip.
|
||||||
|
- When a window loses focus, its selection turns gray, as on macOS.
|
||||||
|
- Errors, warnings, success text and links use Apple's system red, orange,
|
||||||
|
green, blue and purple.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
From `~/.dotfiles`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
stow darwin-breeze helium
|
||||||
|
./darwin-breeze/apply.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
`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. Restart Helium afterwards; T3 Code switches on its own.
|
||||||
|
|
||||||
|
## Changing colors
|
||||||
|
|
||||||
|
The color scheme is the only place colors are defined:
|
||||||
|
|
||||||
|
```
|
||||||
|
.local/share/color-schemes/DarwinBreezeDark.colors
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit it, then run `./darwin-breeze/apply.sh` again. Everything else follows:
|
||||||
|
|
||||||
|
| App | How it gets the colors |
|
||||||
|
| --- | --- |
|
||||||
|
| Qt / KDE apps | the color scheme itself |
|
||||||
|
| GTK apps | Breeze GTK, which `kde-gtk-config` syncs from the scheme |
|
||||||
|
| Tray icons in `tray-icons/` | `ColorScheme-Text`, recolored by Plasma |
|
||||||
|
| Helium | `.local/share/helium-themes/`, generated by `build.py` |
|
||||||
|
| T3 Code | `t3/darwin-breeze.json`, generated by `build.py` and published with `t3 theme set` |
|
||||||
|
| Ghostty | `.config/ghostty/themes/`, generated by `build.py` |
|
||||||
|
|
||||||
|
The generated files are committed so that `stow` alone gives a working setup;
|
||||||
|
don't edit them by hand.
|
||||||
|
|
||||||
|
## T3 Code notes
|
||||||
|
|
||||||
|
- T3 Code ignores symlinked theme files, so the theme isn't stowed;
|
||||||
|
`apply.sh` publishes a copy into `~/.t3/userdata/themes/`.
|
||||||
|
- Every slot of the T3 theme maps to a role in the color scheme (see `t3()` in
|
||||||
|
`build.py`), so a new slot or a different mapping is a change there, not a
|
||||||
|
hand-edited color.
|
||||||
|
|
||||||
|
## Helium notes
|
||||||
|
|
||||||
|
- Helium loads the theme from `~/.local/share/helium-themes/darwinbreeze`
|
||||||
|
through `--load-extension` in `helium/.config/helium-browser-flags.conf`.
|
||||||
|
- 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.
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
## When the colors don't show up
|
||||||
|
|
||||||
|
- In System Settings → Colors, take the accent color from the color scheme. A
|
||||||
|
custom accent, or one taken from the wallpaper, replaces the blue.
|
||||||
|
- Use the Plasma style called "Breeze". "Breeze Dark" and "Breeze Light" carry
|
||||||
|
their own colors, so panels and popups ignore the scheme.
|
||||||
|
- GTK apps follow the scheme only with the Breeze GTK theme. Flatpak apps also
|
||||||
|
need `org.gtk.Gtk3theme.Breeze` installed.
|
||||||
Executable
+43
@@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Regenerate the app themes from the color scheme and apply Darwin Breeze.
|
||||||
|
#
|
||||||
|
# Run `stow darwin-breeze helium` first.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
here="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
data="${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||||
|
|
||||||
|
if [ ! -e "$data/color-schemes/DarwinBreezeDark.colors" ]; then
|
||||||
|
echo "DarwinBreezeDark.colors is not installed; run 'stow darwin-breeze' in ~/.dotfiles" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
python3 -I "$here/build.py"
|
||||||
|
|
||||||
|
plasma-apply-lookandfeel --apply dev.trivk.darwinbreeze.dark
|
||||||
|
|
||||||
|
# plasma-apply-colorscheme skips a scheme that is already active, so edits
|
||||||
|
# to the .colors file would not be picked up. Bounce through stock Breeze.
|
||||||
|
plasma-apply-colorscheme BreezeClassic >/dev/null
|
||||||
|
plasma-apply-colorscheme DarwinBreezeDark >/dev/null
|
||||||
|
|
||||||
|
# Drop the line under the title bar so it blends into the toolbar.
|
||||||
|
kwriteconfig6 --file breezerc --group Windeco --key DrawTitleBarSeparator false
|
||||||
|
|
||||||
|
# A wallpaper-derived accent color would override the blue from the scheme.
|
||||||
|
kwriteconfig6 --file kdeglobals --group General --key AccentColor --delete
|
||||||
|
kwriteconfig6 --file kdeglobals --group General --key accentColorFromWallpaper false
|
||||||
|
|
||||||
|
qdbus6 org.kde.KWin /KWin reconfigure 2>/dev/null \
|
||||||
|
|| dbus-send --session --type=signal /KWin org.kde.KWin.reloadConfig
|
||||||
|
|
||||||
|
# T3 Code skips symlinked theme files, so publish a copy instead of stowing it.
|
||||||
|
t3="$(command -v t3 || echo "$HOME/.t3/bin/t3")"
|
||||||
|
if [ -x "$t3" ]; then
|
||||||
|
"$t3" theme set "$here/t3/darwin-breeze.json" >/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Applied Darwin Breeze"
|
||||||
|
if pgrep -x helium >/dev/null; then
|
||||||
|
echo "Restart Helium to pick up its theme"
|
||||||
|
fi
|
||||||
Executable
+250
@@ -0,0 +1,250 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Generate app themes from the Darwin Breeze KDE color scheme.
|
||||||
|
|
||||||
|
.local/share/color-schemes/DarwinBreezeDark.colors is the only place colors
|
||||||
|
are defined. This script derives from it:
|
||||||
|
|
||||||
|
.local/share/helium-themes/darwinbreeze/manifest.json
|
||||||
|
.config/ghostty/themes/DarwinBreezeDark
|
||||||
|
t3/darwin-breeze.json (published to T3 Code by apply.sh)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import configparser
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
PKG = Path(__file__).resolve().parent
|
||||||
|
SCHEME = PKG / ".local/share/color-schemes/DarwinBreezeDark.colors"
|
||||||
|
HELIUM = PKG / ".local/share/helium-themes/darwinbreeze"
|
||||||
|
GHOSTTY = PKG / ".config/ghostty/themes/DarwinBreezeDark"
|
||||||
|
T3 = PKG / "t3/darwin-breeze.json"
|
||||||
|
|
||||||
|
WHITE = (255, 255, 255)
|
||||||
|
|
||||||
|
# Apple systemCyan; the KDE scheme has no cyan role.
|
||||||
|
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():
|
||||||
|
cp = configparser.ConfigParser(interpolation=None, strict=False)
|
||||||
|
cp.optionxform = str
|
||||||
|
cp.read(SCHEME)
|
||||||
|
|
||||||
|
def color(group, key):
|
||||||
|
return tuple(int(v) for v in cp[f"Colors:{group}"][key].split(","))
|
||||||
|
|
||||||
|
return color
|
||||||
|
|
||||||
|
|
||||||
|
def mix(a, b, t):
|
||||||
|
return tuple(round(x + (y - x) * t) for x, y in zip(a, b))
|
||||||
|
|
||||||
|
|
||||||
|
def hexc(c):
|
||||||
|
return "#{:02x}{:02x}{:02x}".format(*c)
|
||||||
|
|
||||||
|
|
||||||
|
def kwin_compensate(c):
|
||||||
|
"""Pre-distort a color for Chromium on KWin.
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def ch(v):
|
||||||
|
lin = (v / 255) ** 2.2
|
||||||
|
enc = 12.92 * lin if lin <= 0.0031308 else 1.055 * lin ** (1 / 2.4) - 0.055
|
||||||
|
return round(enc * 255)
|
||||||
|
|
||||||
|
return [ch(v) for v in c]
|
||||||
|
|
||||||
|
|
||||||
|
def helium(color):
|
||||||
|
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 ghostty(color):
|
||||||
|
bg = color("View", "BackgroundNormal")
|
||||||
|
fg = color("View", "ForegroundNormal")
|
||||||
|
accent = color("Selection", "BackgroundNormal")
|
||||||
|
accent_text = color("Selection", "ForegroundNormal")
|
||||||
|
|
||||||
|
normal = [
|
||||||
|
mix(bg, fg, 0.15),
|
||||||
|
color("View", "ForegroundNegative"),
|
||||||
|
color("View", "ForegroundPositive"),
|
||||||
|
color("View", "ForegroundNeutral"),
|
||||||
|
color("View", "ForegroundLink"),
|
||||||
|
color("View", "ForegroundVisited"),
|
||||||
|
CYAN,
|
||||||
|
fg,
|
||||||
|
]
|
||||||
|
bright = [
|
||||||
|
mix(bg, fg, 0.45),
|
||||||
|
*(mix(c, WHITE, 0.25) for c in normal[1:7]),
|
||||||
|
mix(fg, WHITE, 0.6),
|
||||||
|
]
|
||||||
|
|
||||||
|
lines = [
|
||||||
|
f"# Generated by darwin-breeze/build.py from {SCHEME.name}",
|
||||||
|
f"background = {hexc(bg)}",
|
||||||
|
f"foreground = {hexc(fg)}",
|
||||||
|
f"cursor-color = {hexc(accent)}",
|
||||||
|
f"cursor-text = {hexc(accent_text)}",
|
||||||
|
f"selection-background = {hexc(accent)}",
|
||||||
|
f"selection-foreground = {hexc(accent_text)}",
|
||||||
|
]
|
||||||
|
lines += [f"palette = {i}={hexc(c)}" for i, c in enumerate(normal + bright)]
|
||||||
|
return "\n".join(lines) + "\n"
|
||||||
|
|
||||||
|
|
||||||
|
def t3(color):
|
||||||
|
"""Every color slot of a T3 Code theme, mapped onto a scheme role."""
|
||||||
|
window, window_text = color("Window", "BackgroundNormal"), color("Window", "ForegroundNormal")
|
||||||
|
view, view_text = color("View", "BackgroundNormal"), color("View", "ForegroundNormal")
|
||||||
|
header, header_text = color("Header", "BackgroundNormal"), color("Header", "ForegroundNormal")
|
||||||
|
button, button_text = color("Button", "BackgroundNormal"), color("Button", "ForegroundNormal")
|
||||||
|
accent, accent_text = color("Selection", "BackgroundNormal"), color("Selection", "ForegroundNormal")
|
||||||
|
unfocused = color("Selection][Inactive", "BackgroundNormal")
|
||||||
|
unfocused_text = color("Selection][Inactive", "ForegroundNormal")
|
||||||
|
muted = color("View", "ForegroundInactive")
|
||||||
|
negative = color("View", "ForegroundNegative")
|
||||||
|
neutral = color("View", "ForegroundNeutral")
|
||||||
|
link = color("View", "ForegroundLink")
|
||||||
|
window_line = mix(window, window_text, 0.115)
|
||||||
|
|
||||||
|
colors = {
|
||||||
|
"canvas": view,
|
||||||
|
"chrome": header,
|
||||||
|
"toolbar": header,
|
||||||
|
"toolbarForeground": header_text,
|
||||||
|
"toolbarBorder": mix(header, header_text, 0.115),
|
||||||
|
"toolbarControl": button,
|
||||||
|
"toolbarControlForeground": button_text,
|
||||||
|
"toolbarControlHover": color("Button", "BackgroundAlternate"),
|
||||||
|
"surface": view,
|
||||||
|
"surfaceRaised": window,
|
||||||
|
"surfaceOverlay": window,
|
||||||
|
"text": view_text,
|
||||||
|
"textMuted": muted,
|
||||||
|
"border": mix(view, view_text, 0.115),
|
||||||
|
"input": mix(view, view_text, 0.3),
|
||||||
|
"focus": mix(view, accent, 0.5),
|
||||||
|
"accent": accent,
|
||||||
|
"accentForeground": accent_text,
|
||||||
|
"secondary": button,
|
||||||
|
"secondaryForeground": button_text,
|
||||||
|
"muted": window,
|
||||||
|
"mutedForeground": color("Window", "ForegroundInactive"),
|
||||||
|
"placeholder": muted,
|
||||||
|
"secondaryLabel": muted,
|
||||||
|
"iconMuted": muted,
|
||||||
|
"error": negative,
|
||||||
|
"errorForeground": negative,
|
||||||
|
"errorSurface": mix(view, negative, 0.1),
|
||||||
|
"warning": neutral,
|
||||||
|
"warningForeground": neutral,
|
||||||
|
"warningSurface": mix(view, neutral, 0.1),
|
||||||
|
"update": link,
|
||||||
|
"updateForeground": link,
|
||||||
|
"updateSurface": mix(view, link, 0.12),
|
||||||
|
"accentSurface": unfocused,
|
||||||
|
"accentSurfaceForeground": unfocused_text,
|
||||||
|
"messageSurface": window,
|
||||||
|
"messageForeground": window_text,
|
||||||
|
"messageAction": accent,
|
||||||
|
"messageActionForeground": accent_text,
|
||||||
|
"messageActionHover": color("Selection", "BackgroundAlternate"),
|
||||||
|
"codeBackground": window,
|
||||||
|
"codeForeground": WHITE,
|
||||||
|
"searchMatchBackground": mix(view, YELLOW, 0.25),
|
||||||
|
"searchMatchForeground": view_text,
|
||||||
|
"searchMatchActiveBackground": YELLOW,
|
||||||
|
"searchMatchActiveForeground": (0, 0, 0),
|
||||||
|
"sidebar": window,
|
||||||
|
"sidebarForeground": window_text,
|
||||||
|
"sidebarMutedForeground": color("Window", "ForegroundInactive"),
|
||||||
|
"sidebarControlSurface": button,
|
||||||
|
"sidebarRowHover": window_line,
|
||||||
|
"sidebarRowActive": unfocused,
|
||||||
|
"sidebarRowSelected": unfocused,
|
||||||
|
"sidebarBorder": window_line,
|
||||||
|
"terminalBackground": view,
|
||||||
|
"terminalForeground": WHITE,
|
||||||
|
"terminalCursor": WHITE,
|
||||||
|
"terminalSelection": mix(view, accent, 0.4),
|
||||||
|
"terminalScrollbar": mix(view, view_text, 0.3),
|
||||||
|
"terminalScrollbarHover": muted,
|
||||||
|
}
|
||||||
|
# T3 Code runs on Chromium too, so it needs the same KWin compensation.
|
||||||
|
return {k: hexc(kwin_compensate(v)) for k, v in colors.items()}
|
||||||
|
|
||||||
|
|
||||||
|
def write(path, text):
|
||||||
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
if path.exists() and path.read_text() == text:
|
||||||
|
return False
|
||||||
|
path.write_text(text)
|
||||||
|
print(f"wrote {path.relative_to(PKG)}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
color = load()
|
||||||
|
manifest = {
|
||||||
|
"manifest_version": 3,
|
||||||
|
"name": "Darwin Breeze",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": f"Generated by darwin-breeze/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)
|
||||||
|
|
||||||
|
write(GHOSTTY, ghostty(color))
|
||||||
|
|
||||||
|
theme = {"version": 1, "name": "Darwin Breeze", "appearance": "dark", "colors": t3(color)}
|
||||||
|
write(T3, json.dumps(theme, indent=2) + "\n")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"name": "Darwin Breeze",
|
||||||
|
"appearance": "dark",
|
||||||
|
"colors": {
|
||||||
|
"canvas": "#181818",
|
||||||
|
"chrome": "#232323",
|
||||||
|
"toolbar": "#232323",
|
||||||
|
"toolbarForeground": "#dfdfdf",
|
||||||
|
"toolbarBorder": "#3a3a3a",
|
||||||
|
"toolbarControl": "#5d5d5d",
|
||||||
|
"toolbarControlForeground": "#e7e7e7",
|
||||||
|
"toolbarControlHover": "#6d6d6d",
|
||||||
|
"surface": "#181818",
|
||||||
|
"surfaceRaised": "#232323",
|
||||||
|
"surfaceOverlay": "#232323",
|
||||||
|
"text": "#dedede",
|
||||||
|
"textMuted": "#9b9b9b",
|
||||||
|
"border": "#313131",
|
||||||
|
"input": "#565656",
|
||||||
|
"focus": "#064b8f",
|
||||||
|
"accent": "#007bff",
|
||||||
|
"accentForeground": "#ffffff",
|
||||||
|
"secondary": "#5d5d5d",
|
||||||
|
"secondaryForeground": "#e7e7e7",
|
||||||
|
"muted": "#232323",
|
||||||
|
"mutedForeground": "#9b9b9b",
|
||||||
|
"placeholder": "#9b9b9b",
|
||||||
|
"secondaryLabel": "#9b9b9b",
|
||||||
|
"iconMuted": "#9b9b9b",
|
||||||
|
"error": "#ff494b",
|
||||||
|
"errorForeground": "#ff494b",
|
||||||
|
"errorSurface": "#311c1e",
|
||||||
|
"warning": "#ff932c",
|
||||||
|
"warningForeground": "#ff932c",
|
||||||
|
"warningSurface": "#31251a",
|
||||||
|
"update": "#3f9dff",
|
||||||
|
"updateForeground": "#3f9dff",
|
||||||
|
"updateSurface": "#1c2936",
|
||||||
|
"accentSurface": "#444444",
|
||||||
|
"accentSurfaceForeground": "#ffffff",
|
||||||
|
"messageSurface": "#232323",
|
||||||
|
"messageForeground": "#dfdfdf",
|
||||||
|
"messageAction": "#007bff",
|
||||||
|
"messageActionForeground": "#ffffff",
|
||||||
|
"messageActionHover": "#1288ff",
|
||||||
|
"codeBackground": "#232323",
|
||||||
|
"codeForeground": "#ffffff",
|
||||||
|
"searchMatchBackground": "#55550e",
|
||||||
|
"searchMatchForeground": "#dedede",
|
||||||
|
"searchMatchActiveBackground": "#ffff00",
|
||||||
|
"searchMatchActiveForeground": "#000000",
|
||||||
|
"sidebar": "#232323",
|
||||||
|
"sidebarForeground": "#dfdfdf",
|
||||||
|
"sidebarMutedForeground": "#9b9b9b",
|
||||||
|
"sidebarControlSurface": "#5d5d5d",
|
||||||
|
"sidebarRowHover": "#3a3a3a",
|
||||||
|
"sidebarRowActive": "#444444",
|
||||||
|
"sidebarRowSelected": "#444444",
|
||||||
|
"sidebarBorder": "#3a3a3a",
|
||||||
|
"terminalBackground": "#181818",
|
||||||
|
"terminalForeground": "#ffffff",
|
||||||
|
"terminalCursor": "#ffffff",
|
||||||
|
"terminalSelection": "#0a4179",
|
||||||
|
"terminalScrollbar": "#565656",
|
||||||
|
"terminalScrollbarHover": "#9b9b9b"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
font-family = "JetBrainsMono Nerd Font"
|
font-family = "JetBrainsMono Nerd Font"
|
||||||
theme = "SpaceGray Eighties"
|
theme = DarwinBreezeDark
|
||||||
cursor-style = bar
|
cursor-style = bar
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Hardware video acceleration (VA-API, AMD radeonsi) on Wayland
|
||||||
|
--ozone-platform-hint=auto
|
||||||
|
--enable-features=AcceleratedVideoDecodeLinuxGL,AcceleratedVideoDecodeLinuxZeroCopyGL,AcceleratedVideoEncoder
|
||||||
|
|
||||||
|
# Darwin Breeze theme, generated by darwin-breeze/build.py
|
||||||
|
--load-extension=~/.local/share/helium-themes/darwinbreeze
|
||||||
Reference in new issue
Block a user