feat(helium): switch to the GTK theme with KWin title buttons

Helium now takes its colors from Breeze GTK instead of a generated
theme extension, which reset the GTK theme on every launch.

- Import window_decorations.css from gtk.css so Helium, which doesn't
  load kde-gtk-config's GTK module, draws the KWin title buttons
  instead of Breeze GTK's round ones.
- Add chromium.css to give the compact layout's address bar and
  button segment the title bar color, so the tab strip is one color.
- Disable WaylandWpColorManagerV1 so KWin doesn't lift Helium's dark
  grays (40 -> 44) and the strip matches KDE title bars.
- Drop the Helium theme from build.py and the helium package.
This commit is contained in:
tri committed 2026-11-03 22:18:52 +07:00
1 parent b14133bbec
commit 09c1e312cb
9 files changed
+74 -184

No files matched your search

+4 -4
View File
@@ -15,7 +15,7 @@ stow -d kde -t "$HOME" spectacle fastfetch
| Package | Details | | Package | Details |
| ---------------------------------- | -------------------------------------------------------- | | ---------------------------------- | -------------------------------------------------------- |
| [theme](theme/README.md) | Darwin Breeze KDE colors and generated app themes | | [theme](theme/README.md) | Darwin Breeze KDE colors and generated app themes |
| [helium](helium/README.md) | Browser flags and the generated Helium theme | | [helium](helium/README.md) | Browser flags; colors come from GTK |
| [fastfetch](fastfetch/README.md) | Konsole configuration and a pre-scaled inline image logo | | [fastfetch](fastfetch/README.md) | Konsole configuration and a pre-scaled inline image logo |
| [spectacle](spectacle/README.md) | Screenshots to clipboard with a notification, no preview | | [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 and qBittorrent tray icons |
@@ -32,6 +32,6 @@ Theme and Spectacle need an additional apply step after stowing their package:
The apply scripts require a running KDE Plasma 6 session. Ngó Sen icons need The apply scripts require a running KDE Plasma 6 session. Ngó Sen icons need
an additional install step described in the tray-icons README. an additional install step described in the tray-icons README.
Packages can be selected independently. Helium includes its generated theme; Packages can be selected independently; Helium follows the Darwin Breeze
it does not require the KDE theme to be installed. Choose either colors only when the theme is applied. Choose either `kde/fastfetch` or
`kde/fastfetch` or `mac/fastfetch`; both own `~/.config/fastfetch/`. `mac/fastfetch`; both own `~/.config/fastfetch/`.
+4 -2
View File
@@ -2,5 +2,7 @@
--ozone-platform-hint=auto --ozone-platform-hint=auto
--enable-features=AcceleratedVideoDecodeLinuxGL,AcceleratedVideoDecodeLinuxZeroCopyGL,AcceleratedVideoEncoder --enable-features=AcceleratedVideoDecodeLinuxGL,AcceleratedVideoDecodeLinuxZeroCopyGL,AcceleratedVideoEncoder
# Darwin Breeze theme, generated by kde/theme/build.py # Don't tag surfaces as sRGB. KWin shows tagged sRGB through a gamma 2.2
--load-extension=~/.local/share/helium-themes/darwinbreeze # curve, which lifts dark grays (40 -> 44), so the tab strip would come out
# lighter than KDE title bars.
--disable-features=WaylandWpColorManagerV1
-2
View File
@@ -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
]
}
}
}
+7 -4
View File
@@ -1,11 +1,14 @@
# Helium # 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 ```sh
stow -d kde -t "$HOME" helium stow -d kde -t "$HOME" helium
``` ```
The theme files are included, so the KDE `theme` package does not need to be Helium takes its colors and window buttons from GTK. In Settings →
stowed to use Helium's theme. To regenerate its colors from the shared color Appearance, set Theme to GTK and turn off "Use system title bar and borders".
scheme, run `python3 kde/theme/build.py` and restart Helium. 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).
+12
View File
@@ -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
View File
@@ -23,11 +23,11 @@ stow -d kde -t "$HOME" theme
``` ```
`apply.sh` regenerates the app themes, applies the global theme, hides the `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 line under the title bar, turns off the wallpaper accent color, gives Helium
the T3 Code theme and installs the VS Code extension. Restart Helium the KWin title buttons and an even tab strip, publishes the T3 Code theme and
afterwards; T3 Code switches on its own. In VS Code, pick "Darwin Breeze Dark" installs the VS Code extension. Restart Helium afterwards; T3 Code switches on its own. In VS
once under Preferences → Color Theme; after later color changes, run Developer: Code, pick "Darwin Breeze Dark" once under Preferences → Color Theme; after
Reload Window. later color changes, run Developer: Reload Window.
Telegram has to import its theme by hand: Settings → Chat Settings → Chat Telegram has to import its theme by hand: Settings → Chat Settings → Chat
background → Choose from file, then pick 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 | | Qt / KDE apps | the color scheme itself |
| GTK apps | Breeze GTK, which `kde-gtk-config` syncs from the scheme | | GTK apps | Breeze GTK, which `kde-gtk-config` syncs from the scheme |
| Tray icons in `kde/tray-icons/` | `ColorScheme-Text`, recolored by Plasma | | 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` | | 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` | | 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 | | 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. are, without gamma compensation, so code looks the same in both apps.
- The terminal palette is generated from the color scheme. - The terminal palette is generated from the color scheme.
- VS Code is Electron, so its workbench colors get the same gamma - 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/`. - The `.vsix` isn't committed; `build.py` packs it from `vscode/`.
## Telegram notes ## 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. colors, are kept as night has them.
- The chat list, top bar and compose bar use the window color; the chat - 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. 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. compensation.
- The `.tdesktop-theme` is a zip, so it isn't committed; `build.py` builds it - The `.tdesktop-theme` is a zip, so it isn't committed; `build.py` builds it
from the night palette and the color scheme. from the night palette and the color scheme.
## Helium notes ## Helium notes
- Helium loads the theme from `~/.local/share/helium-themes/darwinbreeze` - Helium uses the GTK theme (Settings → Appearance → Theme: GTK) with "Use
through `--load-extension` in `kde/helium/.config/helium-browser-flags.conf`. system title bar and borders" off, so the tab strip doubles as the title
Install it separately with `stow -d kde -t "$HOME" helium`. bar. Its colors come from Breeze GTK, which `kde-gtk-config` syncs from
- In Helium's compact layout the active tab and the toolbar segments on either the scheme; there is no Helium theme to generate.
side share one theme color, so the toolbar is the same color as the tab - With the system title bar off, Helium draws the window buttons through
strip and inactive tabs are drawn lighter, as Dolphin does. 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, - 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 which lifts dark grays (40 becomes 44). T3 Code and VS Code get
values for Helium and T3 Code (both Chromium), so the theme files say 35 pre-compensated colors from `build.py`; Helium instead runs with
where the screen shows 40. `--disable-features=WaylandWpColorManagerV1`, so its surfaces go untagged
- Under Settings → Appearance the theme must be Classic, not GTK or QT. and show the GTK colors as they are.
## When the colors don't show up ## When the colors don't show up
+16 -1
View File
@@ -21,6 +21,21 @@ plasma-apply-lookandfeel --apply dev.trivk.darwinbreeze.dark
plasma-apply-colorscheme BreezeClassic >/dev/null plasma-apply-colorscheme BreezeClassic >/dev/null
plasma-apply-colorscheme DarwinBreezeDark >/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. # Drop the line under the title bar so it blends into the toolbar.
kwriteconfig6 --file breezerc --group Windeco --key DrawTitleBarSeparator false kwriteconfig6 --file breezerc --group Windeco --key DrawTitleBarSeparator false
@@ -45,5 +60,5 @@ fi
echo "Applied Darwin Breeze" echo "Applied Darwin Breeze"
if pgrep -x helium >/dev/null; then 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 fi
+3 -53
View File
@@ -4,7 +4,6 @@
.local/share/color-schemes/DarwinBreezeDark.colors is the only place colors .local/share/color-schemes/DarwinBreezeDark.colors is the only place colors
are defined. This script derives from it: 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) t3/darwin-breeze.json (published to T3 Code by apply.sh)
telegram/DarwinBreezeDark.tdesktop-theme (not committed; imported into Telegram by hand) telegram/DarwinBreezeDark.tdesktop-theme (not committed; imported into Telegram by hand)
vscode/ (packed into vscode/darwin-breeze.vsix, installed by apply.sh) vscode/ (packed into vscode/darwin-breeze.vsix, installed by apply.sh)
@@ -24,7 +23,6 @@ from pathlib import Path
HERE = Path(__file__).resolve().parent HERE = Path(__file__).resolve().parent
PKG = HERE PKG = HERE
SCHEME = PKG / ".local/share/color-schemes/DarwinBreezeDark.colors" SCHEME = PKG / ".local/share/color-schemes/DarwinBreezeDark.colors"
HELIUM = PKG.parent / "helium/.local/share/helium-themes/darwinbreeze"
T3 = HERE / "t3/darwin-breeze.json" T3 = HERE / "t3/darwin-breeze.json"
# Telegram Desktop's built-in night theme, used as the base for every key the # 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 # 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. # Apple systemYellow; search highlights in T3 Code.
YELLOW = (255, 255, 0) 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: def load() -> ColorFn:
cp = configparser.ConfigParser(interpolation=None, strict=False) 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 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 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: def ch(v: int) -> int:
@@ -95,40 +90,6 @@ def kwin_compensate(c: Sequence[int]) -> list[int]:
return [ch(v) for v in c] 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]: def ansi(color: ColorFn) -> list[Color]:
"""The 16 colors for the VS Code terminal.""" """The 16 colors for the VS Code terminal."""
bg = color("View", "BackgroundNormal") 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 = {k: pins.get(k) or recolor(c) for k, c in base.items()}
colors.update(pins) 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())} 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: def main() -> None:
color = load() 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)} theme = {"version": 1, "name": "Darwin Breeze", "appearance": "dark", "colors": t3(color)}
write(T3, json.dumps(theme, indent=2) + "\n") write(T3, json.dumps(theme, indent=2) + "\n")