nexoniarz-config-nixos/modules/scripts/gtk-theme-set.sh
Nexoniarz d1ff0a11e0 Add Qt/GTK2 theming, default apps, LibreOffice; fix display.conf race
- Add qt-theme-set: a working Qt theming pipeline via qt6ct (the
  QT_QPA_PLATFORMTHEME=qt6ct env var was pointing at a platform theme
  plugin that wasn't even installed, so every Qt app fell back to its
  own default style). Also regenerates kdeglobals' KColorScheme groups
  and sets QT_QUICK_CONTROLS_STYLE=org.kde.desktop for Kirigami-based
  KDE apps, whose QML-drawn chrome ignores QPalette/qt6ct entirely.
  Gwenview's dialogs/content now follow the theme; its toolbar/statusbar
  chrome is a known remaining gap tied to Kirigami's platform-theme
  detection outside a full Plasma session
- Add GTK2 compat (~/.gtkrc-2.0: icon theme + font follow the theme;
  no dark variant exists for GTK2's Adwaita engine)
- Add modules/default-apps.nix: Gwenview/Ark as system-default image
  viewer/archive manager via /etc/xdg/mimeapps.list, LibreOffice
  (Qt6 build), and a working Thunar "Open Terminal Here" (it shipped
  calling exo-open, which isn't installed and never resolved)
- Fix display-set.sh: mktemp defaulted to /tmp, a different filesystem
  than ~/.config/hypr here, making the mv into display.conf a
  non-atomic copy+unlink. Hyprland's file watcher could catch it
  mid-replace and throw "source= globbing error: found no match" on
  any monitor mode/orientation change. Stress-tested with 60 concurrent
  write+reload cycles after the fix with zero errors
2026-08-30 16:51:39 +02:00

132 lines
4.4 KiB
Shell

#!/usr/bin/env bash
# Regenerates GTK3/4 CSS + settings.ini to match the current Quickshell
# theme (accent color + dark/light mode). These used to be static,
# Nix-rebuild-only files (symlinked straight into the store) — this makes
# them live-editable instead, the same way cursor.conf/display.conf work,
# so the Theme picker can actually reach GTK apps like Thunar.
set -euo pipefail
accent="${1:?usage: gtk-theme-set <accent> <bg> <bgAlt> <fg> <fgDim> <border> <dark:1|0>}"
bg="${2:?bg required}"
bg_alt="${3:?bgAlt required}"
fg="${4:?fg required}"
fg_dim="${5:?fgDim required}"
border="${6:?border required}"
dark="${7:?dark required}"
dir3="$HOME/.config/gtk-3.0"
dir4="$HOME/.config/gtk-4.0"
mkdir -p "$dir3" "$dir4"
css_file=$(mktemp)
cat > "$css_file" <<EOF
/* Squared corners + accent colors, generated by gtk-theme-set from the
Quickshell Theme picker — GTK's CSS is a subset of real CSS: no
!important, and zero still needs a unit.
The @define-color block matters more than it looks: plain selector
overrides (window, .background, .view, ...) only get you so far —
Thunar's icon-view content area and sidebar tree view turned out to
pull their actual fill color from these named theme variables
internally, not from the generic background-color cascade. Verified
live: without redefining theme_base_color specifically, the sidebar
and file grid stayed white no matter how broad the selector list got. */
@define-color theme_bg_color $bg;
@define-color theme_base_color $bg;
@define-color theme_fg_color $fg;
@define-color theme_text_color $fg;
@define-color theme_selected_bg_color $accent;
@define-color theme_selected_fg_color $bg;
@define-color borders $border;
* {
border-radius: 0px;
-gtk-outline-radius: 0px;
}
window, .background, .view, iconview, treeview, treeview.view, list, row,
notebook, notebook > stack, scrolledwindow, viewport {
background-color: $bg;
color: $fg;
}
iconview.cell, iconview text {
background-color: $bg;
color: $fg;
}
treeview.view:selected, row:selected, iconview:selected {
background-color: $accent;
color: $bg;
}
headerbar, .titlebar {
background-color: $bg_alt;
color: $fg;
border-color: $border;
box-shadow: none;
}
button {
border-color: $border;
}
button:hover {
background-color: $bg_alt;
}
selection, *:selected {
background-color: $accent;
color: $bg;
}
EOF
cp "$css_file" "$dir3/gtk.css"
cp "$css_file" "$dir4/gtk.css"
rm -f "$css_file"
prefer_dark="false"
theme_name="Adwaita"
icon_theme="Gruvbox-Plus-Light"
if [ "$dark" = "1" ]; then
prefer_dark="true"
theme_name="Adwaita-dark"
icon_theme="Gruvbox-Plus-Dark"
fi
ini_file=$(mktemp)
cat > "$ini_file" <<EOF
[Settings]
gtk-application-prefer-dark-theme=$prefer_dark
gtk-theme-name=$theme_name
gtk-icon-theme-name=$icon_theme
gtk-font-name=Noto Sans, 10
gtk-enable-animations=true
EOF
cp "$ini_file" "$dir3/settings.ini"
cp "$ini_file" "$dir4/settings.ini"
rm -f "$ini_file"
# settings.ini alone isn't enough: GTK3 binds gtk-theme-name/icon-theme-name
# to org.gnome.desktop.interface via GSettings whenever that schema and a
# dconf backend are present (they are here — dconf-service was already
# running), and that binding wins over settings.ini unconditionally. This
# machine's dconf database had hard values left over (gtk-theme='Breeze',
# icon-theme='breeze') that silently overrode every settings.ini edit —
# which is why neither accent/dark-mode nor the Gruvbox icon switch ever
# reached Thunar. Writing the same values to dconf keeps both sources in
# sync so it doesn't matter which one GTK actually reads from.
if command -v dconf >/dev/null 2>&1; then
color_scheme="default"
[ "$dark" = "1" ] && color_scheme="prefer-dark"
dconf write /org/gnome/desktop/interface/gtk-theme "'$theme_name'"
dconf write /org/gnome/desktop/interface/icon-theme "'$icon_theme'"
dconf write /org/gnome/desktop/interface/color-scheme "'$color_scheme'"
fi
# GTK2 compat: separate config format (~/.gtkrc-2.0, not settings.ini),
# and no live theme-switching mechanism at all — GTK2 apps only read this
# at their own startup. Only icon theme and font actually follow the
# current theme; gnome-themes-extra's bundled GTK2 Adwaita engine has no
# dark variant to switch to (GTK2 predates that concept), so gtk-theme-
# name here is always the one real option, not a broken attempt at dark
# mode.
cat > "$HOME/.gtkrc-2.0" <<EOF
gtk-theme-name="Adwaita"
gtk-icon-theme-name="$icon_theme"
gtk-font-name="Noto Sans 10"
EOF