# app-theme-awareness

User-level, no root.

## Goal
Make external apps (Chrome/Chromium, Electron, Firefox, GTK, Qt) **follow
Caelestia's light/dark mode** automatically — dark when Caelestia is dark.

## Why they don't today
Modern apps read one signal: `org.freedesktop.appearance` → `color-scheme`,
published by **xdg-desktop-portal**. By default that value is **0
("no preference")** because nothing sets it — `gsettings
org.gnome.desktop.interface color-scheme` is `'default'`. So every app defaults
to light. All portal pieces are already installed (`xdg-desktop-portal`,
`-gtk`, `-hyprland`); `libadwaita` is present.

## How this works
- **`nosignal-app-theme-sync`**: reads `caelestia scheme get` ("Mode: dark|
  light") and sets:
  - `gsettings org.gnome.desktop.interface color-scheme` → `prefer-dark` /
    `prefer-light`. xdg-desktop-portal-gtk republishes this as the freedesktop
    appearance `color-scheme`, which **Chrome, Electron, Firefox, GTK4/libadwaita
    and Qt6 honor** (UI + web `prefer-color-scheme`).
  - `gtk-application-prefer-dark-theme` in `gtk-3.0`/`gtk-4.0` `settings.ini`
    for legacy GTK3 apps that ignore the portal.
- **`nosignal-app-theme.path` + `.service`** (user units, mirroring NoSignal's
  `hyprmoncfgd-rescan.path`): watch `~/.local/state/caelestia/scheme.json` and
  re-run the sync on every scheme change, and run it once at login. So flipping
  Caelestia light↔dark flips the apps live.
- **`portals.conf`**: pins the Settings portal backend to `gtk` (keeping
  Hyprland's portal default for screencast), so the appearance value is served
  reliably. Installed only if the user has no `portals.conf`.

`install-app-theme-awareness.sh` does all of it idempotently — entirely
user-level (no root, no pacman hook).

## Per-app notes
- **Chrome/Chromium (Wayland):** follows the portal automatically. If the UI
  stays light, set `chrome://settings` → Appearance → **GTK / "Use system"**.
- **Qt:** `QT_QPA_PLATFORMTHEME=qtengine` is already set; Qt6 honors the portal.
  Old Qt5 apps may need a dark qt5ct/Kvantum style (out of scope).
- **GTK3 dark fidelity:** prefer-dark uses Adwaita's built-in dark rendering. For
  a fuller dark GTK3 theme the builder can add `gnome-themes-extra` (ships
  `Adwaita-dark`) — optional.

## Builder integration
Ship the sync script in the layer bin, the two user units (enabled by default,
like the other NoSignal user units), and seed `portals.conf`. Ideally Caelestia
itself could set `color-scheme` when its scheme flips; until then these units
bridge it. Mode is read from `caelestia scheme get`, so it tracks the dynamic
Material scheme.

## Verify (after install)
```
caelestia scheme set -m light   # or via the Caelestia UI
gsettings get org.gnome.desktop.interface color-scheme   # -> 'prefer-light'
caelestia scheme set -m dark
gsettings get org.gnome.desktop.interface color-scheme   # -> 'prefer-dark'
# Chrome/GTK apps follow within a moment.
```

## Files
- `nosignal-app-theme-sync` — mode → portal/GTK sync.
- `nosignal-app-theme.service` / `.path` — login run + watch-on-change.
- `portals.conf` — Settings backend = gtk.
- `install-app-theme-awareness.sh` — idempotent user-level installer.
- `migrations/1781442000-app-theme-awareness.sh` — delegates to it.
