diff --git a/configuration.nix b/configuration.nix index 9f3a031..0e630c6 100644 --- a/configuration.nix +++ b/configuration.nix @@ -12,6 +12,7 @@ ./modules/users.nix # User accounts and global configurations ./modules/apps.nix # All installed packages: apps, CLI tools, dev toolchains ./modules/scripts.nix # Custom system scripts and helpers + ./modules/default-apps.nix # Default app associations (terminal, image viewer, archives), LibreOffice ]; # Do not change this value. Read documentation before updating. diff --git a/dotfiles/quickshell/Theme.qml b/dotfiles/quickshell/Theme.qml index 5de1909..f06537a 100644 --- a/dotfiles/quickshell/Theme.qml +++ b/dotfiles/quickshell/Theme.qml @@ -104,6 +104,11 @@ Item { theme.dark ? "1" : "0"]; gtkSyncProc.running = true; + qtSyncProc.command = ["qt-theme-set", + theme.accent, theme.bg, theme.bgAlt, theme.fg, theme.fgDim, theme.border, + theme.dark ? "1" : "0"]; + qtSyncProc.running = true; + kittySyncProc.command = ["kitty-theme-set", theme.accent, theme.bg, theme.bgAlt, theme.fg, theme.fgDim, theme.border]; kittySyncProc.running = true; @@ -117,6 +122,7 @@ Item { Process { id: saveProc } Process { id: hyprSyncProc } Process { id: gtkSyncProc } + Process { id: qtSyncProc } Process { id: kittySyncProc } Process { id: rofiSyncProc } Process { diff --git a/hyprland/hyprland.conf b/hyprland/hyprland.conf index 0683b41..8d9c604 100644 --- a/hyprland/hyprland.conf +++ b/hyprland/hyprland.conf @@ -42,6 +42,13 @@ env = XDG_SESSION_DESKTOP,Hyprland env = GDK_BACKEND,wayland,x11 env = QT_QPA_PLATFORM,wayland;xcb env = QT_QPA_PLATFORMTHEME,qt6ct +# Kirigami-based KDE apps (confirmed live: Gwenview's toolbar/statusbar) +# draw their chrome in QML, not QWidget — outside a real Plasma session +# they default to their own hardcoded light "Basic" QQC2 style instead of +# reading qt6ct or kdeglobals at all. org.kde.desktop is the QQC2 style +# that actually pulls from KColorScheme/kdeglobals like the rest of the +# theming pipeline here does. +env = QT_QUICK_CONTROLS_STYLE,org.kde.desktop # --- Input ------------------------------------------------------------ input { diff --git a/modules/default-apps.nix b/modules/default-apps.nix new file mode 100644 index 0000000..0ef6b29 --- /dev/null +++ b/modules/default-apps.nix @@ -0,0 +1,65 @@ +{ config, pkgs, lib, ... }: + +{ + environment.systemPackages = with pkgs; [ + libreoffice-qt6 # Qt6-styled build — fits the Qt theming work in theme.nix + # better than the default GTK3 build would. + ]; + + # System-level fallback defaults (XDG spec: only consulted for a + # mimetype the user's own ~/.config/mimeapps.list doesn't already + # claim), so a future "Open With" choice always wins over this without + # needing to touch it. Mimetype lists taken directly from Gwenview's + # and Ark's own .desktop files, not guessed. + # + # One mimetype=desktopfile pair per line: the semicolon only separates + # multiple desktop-file candidates for the SAME key, it doesn't chain + # separate mimetype=value pairs on one line — mimeapps.list parsers + # (verified against xdg-utils' own xdg-mime script) match by scanning + # for a line that STARTS WITH "mimetype=", so cramming several pairs + # onto one semicolon-joined line silently hides every key after the + # first from ever being found. + environment.etc."xdg/mimeapps.list".text = + let + gwenviewMimes = [ + "inode/directory" "image/avif" "image/gif" "image/heif" "image/jpeg" + "image/jxl" "image/png" "image/bmp" "image/x-eps" "image/x-icns" + "image/x-ico" "image/x-portable-bitmap" "image/x-portable-graymap" + "image/x-portable-pixmap" "image/x-xbitmap" "image/x-xpixmap" + "image/tiff" "image/x-psd" "image/x-webp" "image/webp" "image/x-tga" + "image/x-xcf" "image/openraster" "image/svg+xml" "image/svg+xml-compressed" + ]; + arkMimes = [ + "application/x-cd-image" "application/x-bcpio" "application/x-cpio" + "application/x-cpio-compressed" "application/x-rpm" "application/x-compress" + "application/gzip" "application/x-bzip" "application/x-bzip2" + "application/x-lzma" "application/x-xz" "application/zstd" "application/x-lz4" + "application/x-source-rpm" "application/vnd.debian.binary-package" + "application/vnd.ms-cab-compressed" "application/x-archive" "application/x-tar" + "application/x-compressed-tar" "application/x-bzip-compressed-tar" + "application/x-bzip2-compressed-tar" "application/x-tarz" + "application/x-xz-compressed-tar" "application/x-lzma-compressed-tar" + "application/x-7z-compressed" "application/vnd.rar" "application/zip" + "application/x-java-archive" "application/x-arj" + ]; + line = desktop: mime: "${mime}=${desktop}"; + in + '' + [Default Applications] + ${lib.concatMapStringsSep "\n" (line "org.kde.gwenview.desktop") gwenviewMimes} + ${lib.concatMapStringsSep "\n" (line "org.kde.ark.desktop") arkMimes} + ''; + + # Thunar's own "Open Terminal Here" custom action (Edit > Configure + # Custom Actions) shipped pointing at `exo-open --launch + # TerminalEmulator` — exo isn't installed on this system at all (no + # XFCE session, so its helpers.rc mechanism has nothing to resolve + # against), so the action silently did nothing. `f`, not `w`: only + # creates this baseline for a fresh account — once it exists, further + # edits made through Thunar's own UI (adding more custom actions) are + # never overwritten by a rebuild. + systemd.tmpfiles.rules = [ + "d /home/nexoniarz/.config/Thunar 0755 nexoniarz users -" + ''f /home/nexoniarz/.config/Thunar/uca.xml 0644 nexoniarz users - utilities-terminalOpen Terminal Here1788014825097143-1kitty --working-directory %fOpen a terminal in this folder*'' + ]; +} diff --git a/modules/scripts.nix b/modules/scripts.nix index fa6d770..ffa3cd7 100644 --- a/modules/scripts.nix +++ b/modules/scripts.nix @@ -12,6 +12,7 @@ let displaySet = pkgs.writeShellScriptBin "display-set" (builtins.readFile ./scripts/display-set.sh); hyprThemeSet = pkgs.writeShellScriptBin "hypr-theme-set" (builtins.readFile ./scripts/hypr-theme-set.sh); gtkThemeSet = pkgs.writeShellScriptBin "gtk-theme-set" (builtins.readFile ./scripts/gtk-theme-set.sh); + qtThemeSet = pkgs.writeShellScriptBin "qt-theme-set" (builtins.readFile ./scripts/qt-theme-set.sh); kittyThemeSet = pkgs.writeShellScriptBin "kitty-theme-set" (builtins.readFile ./scripts/kitty-theme-set.sh); rofiThemeSet = pkgs.writeShellScriptBin "rofi-theme-set" (builtins.readFile ./scripts/rofi-theme-set.sh); listCursorThemes = pkgs.writeShellScriptBin "list-cursor-themes" (builtins.readFile ./scripts/list-cursor-themes.sh); @@ -36,6 +37,7 @@ in displaySet hyprThemeSet gtkThemeSet + qtThemeSet kittyThemeSet rofiThemeSet listCursorThemes diff --git a/modules/scripts/display-set.sh b/modules/scripts/display-set.sh index 5471e6c..b7c74f5 100644 --- a/modules/scripts/display-set.sh +++ b/modules/scripts/display-set.sh @@ -25,7 +25,15 @@ touch "$conf" line="monitor = $descriptor" if grep -q "^monitor = $mon," "$conf" 2>/dev/null; then - tmp=$(mktemp) + # mktemp in the same directory as $conf, not the default /tmp: /tmp is + # a different filesystem here, which makes `mv` below a non-atomic + # copy+unlink instead of a rename — Hyprland's file watcher (it + # watches every `source=`d file, including this one) could catch the + # destination mid-replace and its `source=` glob would find nothing, + # throwing "globbing error: found no match" (observed live after an + # orientation change, which always hits this branch since DP-1 + # already has an existing line by then). + tmp=$(mktemp "$conf.XXXXXX") awk -v prefix="monitor = $mon," -v newline="$line" ' index($0, prefix) == 1 { print newline; next } { print } ' "$conf" > "$tmp" diff --git a/modules/scripts/gtk-theme-set.sh b/modules/scripts/gtk-theme-set.sh index d656beb..efa4034 100644 --- a/modules/scripts/gtk-theme-set.sh +++ b/modules/scripts/gtk-theme-set.sh @@ -117,3 +117,16 @@ if command -v dconf >/dev/null 2>&1; then 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" < "$color_file" < "$dir/qt6ct.conf" < "$HOME/.config/kdeglobals" <