fix: add wayland dev headers and scanner for pywayland build on NixOS

This commit is contained in:
Celes Renata
2026-05-08 15:55:01 -07:00
commit f143bce273
740 changed files with 86018 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
# Package definitions for dots-hyprland utilities
{ pkgs }:
{
update-flake = pkgs.writeShellScriptBin "update-flake"
(builtins.readFile ./scripts/update-flake.sh);
test-python-env = pkgs.writeShellScriptBin "test-python-env"
(builtins.readFile ./scripts/test-python-env.sh);
test-quickshell = pkgs.writeShellScriptBin "test-quickshell"
(builtins.readFile ./scripts/test-quickshell.sh);
compare-modes = pkgs.writeShellScriptBin "compare-modes"
(builtins.readFile ./scripts/compare-modes.sh);
# QML directory generator for quickshell
generate-qmldir = pkgs.writeShellScriptBin "generate-qmldir"
(builtins.readFile ./scripts/generate-qmldir.sh);
# Quickshell reset script
quickshell-reset = pkgs.writeShellScriptBin "quickshell-reset.sh"
(builtins.readFile ./scripts/quickshell-reset.sh);
}
+165
View File
@@ -0,0 +1,165 @@
# Package mappings from dots-hyprland meta-packages to nixpkgs
# Direct mapping from PKGBUILD files in arch-packages/
{ lib, pkgs }:
let
# Import utility packages
utilityPackages = import ./default.nix { inherit pkgs; };
# illogical-impulse-basic PKGBUILD
basicPackages = with pkgs; [
axel
bc
coreutils
cliphist
cmake
curl
rsync
wget
ripgrep
jq
meson
xdg-user-dirs
];
# illogical-impulse-widgets PKGBUILD
widgetPackages = with pkgs; [
fuzzel
glib # for gsettings
gsettings-desktop-schemas # GNOME schemas for non-GNOME environments
hypridle
hyprutils
hyprlock
hyprpicker
networkmanagerapplet # nm-connection-editor
pkgs.quickshell
translate-shell
wlogout
# Qt modules needed for quickshell widgets
kdePackages.qt5compat # For Qt5Compat.GraphicalEffects
kdePackages.qtdeclarative # For QML
kdePackages.kdialog
kdePackages.qtwayland # For Wayland support
kdePackages.qtpositioning # For Weather service location features
kdePackages.qtlocation # Additional location services for QtPositioning
# KDE components for bluetooth and network management
kdePackages.kcmutils # Provides kcmshell6
kdePackages.kde-cli-tools # KDE CLI tools
kdePackages.bluez-qt # Bluetooth QML module
kdePackages.bluedevil # KDE bluetooth manager
kdePackages.plasma-nm # KDE network manager
kdePackages.networkmanager-qt # NetworkManager QML bindings
kdePackages.modemmanager-qt # ModemManager QML bindings
kdePackages.kconfig # KDE config module
kdePackages.kirigami # KDE UI framework
kdePackages.kcoreaddons # KDE core addons
kdePackages.ki18n # KDE internationalization
# Wrapper scripts for KDE tools with proper QML paths
(pkgs.writeShellScriptBin "kcmshell6-bluetooth" ''
export QML2_IMPORT_PATH="${pkgs.kdePackages.bluez-qt}/lib/qt-6/qml:${pkgs.kdePackages.bluedevil}/lib/qt-6/qml:${pkgs.kdePackages.plasma-nm}/lib/qt-6/qml:${pkgs.kdePackages.kconfig}/lib/qt-6/qml:${pkgs.kdePackages.kirigami}/lib/qt-6/qml"
exec ${pkgs.kdePackages.kcmutils}/bin/kcmshell6 kcm_bluetooth
'')
(pkgs.writeShellScriptBin "kcmshell6-network" ''
export QML2_IMPORT_PATH="${pkgs.kdePackages.plasma-nm}/lib/qt-6/qml:${pkgs.kdePackages.kconfig}/lib/qt-6/qml:${pkgs.kdePackages.kirigami}/lib/qt-6/qml:${pkgs.kdePackages.networkmanager-qt}/lib/qt-6/qml:${pkgs.kdePackages.modemmanager-qt}/lib/qt-6/qml:${pkgs.kdePackages.kcoreaddons}/lib/qt-6/qml:${pkgs.kdePackages.ki18n}/lib/qt-6/qml"
exec ${pkgs.kdePackages.kcmutils}/bin/kcmshell6 kcm_networkmanagement
'')
(pkgs.writeShellScriptBin "plasmawindowed-network" ''
export QML2_IMPORT_PATH="${pkgs.kdePackages.plasma-nm}/lib/qt-6/qml:${pkgs.kdePackages.kconfig}/lib/qt-6/qml:${pkgs.kdePackages.kirigami}/lib/qt-6/qml:${pkgs.kdePackages.networkmanager-qt}/lib/qt-6/qml:${pkgs.kdePackages.modemmanager-qt}/lib/qt-6/qml:${pkgs.kdePackages.kcoreaddons}/lib/qt-6/qml:${pkgs.kdePackages.ki18n}/lib/qt-6/qml"
exec ${pkgs.kdePackages.kde-cli-tools}/bin/plasmawindowed org.kde.plasma.networkmanagement
'')
];
# illogical-impulse-hyprland PKGBUILD
# Note: hyprland itself should be installed system-wide via programs.hyprland.enable
hyprlandPackages = with pkgs; [
hypridle
hyprcursor
# hyprland # Removed - use system hyprland instead
hyprland-qtutils
# hyprland-qt-support -> might be in hyprland-qtutils
hyprlang
hyprlock
hyprpicker
hyprsunset
hyprutils
hyprwayland-scanner
xdg-desktop-portal-hyprland
wl-clipboard
];
# illogical-impulse-python PKGBUILD (system dependencies)
pythonSystemPackages = with pkgs; [
clang
# uv -> not needed in NixOS approach, we use pip directly
gtk4
libadwaita
libsoup_3 # libsoup3
libportal-gtk4
gobject-introspection
sassc
opencv4 # python-opencv
# Additional system libraries needed for Python packages
stdenv.cc.cc.lib # provides libstdc++.so.6
glibc
zlib
libffi
openssl
bzip2
xz
ncurses
readline
sqlite
];
# Additional packages that might be needed
audioPackages = with pkgs; [
pipewire
wireplumber
pavucontrol
playerctl
];
# Font packages (from installer analysis)
fontPackages = with pkgs; [
# Rubik font (installer sets this as default)
# Note: might need to add custom font derivation
noto-fonts
noto-fonts-cjk-sans
noto-fonts-color-emoji
font-awesome
material-design-icons
nerd-fonts.jetbrains-mono
nerd-fonts.fira-code
];
# Theme and appearance packages
themePackages = with pkgs; [
matugen # for Material You color generation
# Additional theme packages as needed
];
in
{
inherit
basicPackages
widgetPackages
hyprlandPackages
pythonSystemPackages
audioPackages
fontPackages
themePackages;
# Combined package sets for different use cases
essentialPackages = basicPackages ++ widgetPackages ++ hyprlandPackages ++
(builtins.attrValues utilityPackages);
allPackages = basicPackages ++ widgetPackages ++ hyprlandPackages ++
pythonSystemPackages ++ audioPackages ++ fontPackages ++ themePackages ++
(builtins.attrValues utilityPackages);
# Minimal set for testing
minimalPackages = basicPackages ++ widgetPackages ++ (builtins.attrValues utilityPackages);
}
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env bash
echo "🔍 dots-hyprland Configuration Modes"
echo "===================================="
echo ""
echo "📋 Available modes:"
echo ""
echo "1. 🔒 DECLARATIVE MODE"
echo " • Files managed by Home Manager"
echo " • Read-only configuration"
echo " • Automatic updates with 'home-manager switch'"
echo " • Best for: Set-and-forget users"
echo " • Build: nix build .#homeConfigurations.declarative.activationPackage"
echo ""
echo "2. ✏️ WRITABLE MODE"
echo " • Files staged to ~/.configstaging"
echo " • User copies/modifies configuration"
echo " • Full control over files"
echo " • Best for: Customization and development"
echo " • Build: nix build .#homeConfigurations.writable.activationPackage"
echo ""
echo "🚀 Quick start:"
echo " # For declarative mode:"
echo " nix build .#homeConfigurations.declarative.activationPackage && ./result/activate"
echo ""
echo " # For writable mode:"
echo " nix build .#homeConfigurations.writable.activationPackage && ./result/activate"
echo " ~/.local/bin/initialSetup.sh"
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
echo "🚀 dots-hyprland self-contained installer replication"
echo ""
echo "📋 Available commands:"
echo " update-flake - Manage flake inputs"
echo " compare-modes - Compare declarative vs writable modes"
echo " test-python-env - Test Python virtual environment"
echo " test-quickshell - Test quickshell with config"
echo ""
echo "🔄 Flake management:"
echo " update-flake status - Show current flake status"
echo " update-flake update - Update flake inputs"
echo " update-flake verify - Test configurations build"
echo ""
echo "🎯 Build configurations:"
echo " nix build .#homeConfigurations.declarative.activationPackage"
echo " nix build .#homeConfigurations.writable.activationPackage"
echo ""
echo "📁 Local structure:"
echo " ./configs/ - All dots-hyprland configurations"
echo " ./modules/ - NixOS/Home Manager modules"
echo " ./packages/ - Utility scripts and packages"
echo ""
echo "🔑 Self-contained: No external dependencies on dots-hyprland repo!"
echo "📁 Branch: $(git branch --show-current 2>/dev/null || echo 'unknown')"
echo ""
echo "💡 Run 'update-flake help' for full options"
+223
View File
@@ -0,0 +1,223 @@
#!/usr/bin/env bash
# Dynamic qmldir generator for quickshell configurations
# This script automatically generates qmldir files based on actual QML files present
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
log() {
echo -e "${GREEN}[qmldir-gen]${NC} $1" >&2
}
warn() {
echo -e "${YELLOW}[qmldir-gen]${NC} WARNING: $1" >&2
}
error() {
echo -e "${RED}[qmldir-gen]${NC} ERROR: $1" >&2
}
# Function to check if a QML file is a singleton
is_singleton() {
local file="$1"
grep -q "pragma Singleton" "$file" 2>/dev/null
}
# Function to generate qmldir for a directory
generate_qmldir() {
local dir="$1"
local module_name="$2"
local qmldir_file="$dir/qmldir"
if [[ ! -d "$dir" ]]; then
warn "Directory $dir does not exist, skipping"
return 0
fi
log "Generating qmldir for $dir (module: $module_name)"
# Start with module declaration
echo "module $module_name" > "$qmldir_file"
echo "" >> "$qmldir_file"
# Find all QML files and add them
local count=0
local singleton_count=0
while IFS= read -r -d '' file; do
local basename=$(basename "$file" .qml)
# Skip files that start with lowercase (usually internal components)
if [[ "$basename" =~ ^[A-Z] ]]; then
if is_singleton "$file"; then
echo "singleton $basename 1.0 $(basename "$file")" >> "$qmldir_file"
((singleton_count++))
else
echo "$basename 1.0 $(basename "$file")" >> "$qmldir_file"
fi
((count++))
fi
done < <(find "$dir" -maxdepth 1 -name "*.qml" -type f -print0 | sort -z) || true
log " → Registered $count components ($singleton_count singletons) in $qmldir_file"
}
# Main function
main() {
local quickshell_dir="${1:-$HOME/.config/quickshell/ii}"
if [[ ! -d "$quickshell_dir" ]]; then
error "Quickshell directory $quickshell_dir does not exist"
exit 1
fi
log "Generating qmldir files for quickshell configuration at $quickshell_dir"
# Generate main qmldir (root level components)
log "Processing root directory..."
generate_qmldir "$quickshell_dir" "qs"
# Copy main qmldir to qs subdirectory for proper module resolution
if [[ -f "$quickshell_dir/qmldir" && -d "$quickshell_dir/qs" ]]; then
log "Copying main qmldir to qs subdirectory for module resolution..."
cp "$quickshell_dir/qmldir" "$quickshell_dir/qs/qmldir"
log " → Main qmldir copied to qs/qmldir"
# Also copy the root-level QML files that are referenced in the qmldir
log "Copying root-level QML files to qs subdirectory..."
while IFS= read -r qml_file; do
if [[ -f "$quickshell_dir/$qml_file" ]]; then
cp "$quickshell_dir/$qml_file" "$quickshell_dir/qs/$qml_file"
log " → Copied $qml_file to qs/$qml_file"
fi
done < <(grep "\.qml$" "$quickshell_dir/qmldir" | awk '{print $NF}' || true)
fi
# Generate qmldir for modules directory
if [[ -d "$quickshell_dir/modules" ]]; then
log "Processing modules directory..."
generate_qmldir "$quickshell_dir/modules" "qs.modules"
# Generate qmldir for each module subdirectory
while IFS= read -r -d '' module_dir; do
local module_name=$(basename "$module_dir")
log "Processing module: $module_name"
generate_qmldir "$module_dir" "qs.modules.$module_name"
# Handle nested subdirectories (like common/functions, common/widgets)
while IFS= read -r -d '' nested_dir; do
local nested_name=$(basename "$nested_dir")
log "Processing nested module: $module_name/$nested_name"
generate_qmldir "$nested_dir" "qs.modules.$module_name.$nested_name"
done < <(find "$module_dir" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z) || true
done < <(find "$quickshell_dir/modules" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z)
fi
# Generate qmldir for services directory
if [[ -d "$quickshell_dir/services" ]]; then
log "Processing services directory..."
generate_qmldir "$quickshell_dir/services" "qs.services"
# Generate qmldir for each service subdirectory
while IFS= read -r -d '' service_dir; do
local service_name=$(basename "$service_dir")
log "Processing service: $service_name"
generate_qmldir "$service_dir" "qs.services.$service_name"
done < <(find "$quickshell_dir/services" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z)
fi
# Generate qmldir for qs directory (if it exists)
if [[ -d "$quickshell_dir/qs" ]]; then
log "Processing qs directory..."
# Don't overwrite the main qmldir file we copied earlier
# Only generate qmldir for subdirectories of qs
# Generate qmldir for qs subdirectories
while IFS= read -r -d '' qs_subdir; do
local subdir_name=$(basename "$qs_subdir")
log "Processing qs/$subdir_name"
generate_qmldir "$qs_subdir" "qs.qs.$subdir_name"
# Handle nested qs subdirectories (like qs/modules/common, qs/services/ai)
while IFS= read -r -d '' nested_qs_dir; do
local nested_name=$(basename "$nested_qs_dir")
log "Processing nested qs: $subdir_name/$nested_name"
generate_qmldir "$nested_qs_dir" "qs.qs.$subdir_name.$nested_name"
# Handle deeply nested directories (like qs/modules/common/functions)
while IFS= read -r -d '' deep_nested_dir; do
local deep_name=$(basename "$deep_nested_dir")
log "Processing deep nested qs: $subdir_name/$nested_name/$deep_name"
generate_qmldir "$deep_nested_dir" "qs.qs.$subdir_name.$nested_name.$deep_name"
done < <(find "$nested_qs_dir" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z) || true
done < <(find "$qs_subdir" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z) || true
done < <(find "$quickshell_dir/qs" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z)
fi
log "✅ qmldir generation complete!"
log "📊 Summary:"
find "$quickshell_dir" -name "qmldir" -type f | while read -r qmldir_file; do
local component_count=$(grep -c "\.qml$" "$qmldir_file" || echo "0")
local singleton_count=$(grep -c "^singleton" "$qmldir_file" || echo "0")
local relative_path=${qmldir_file#$quickshell_dir/}
log "$relative_path: $component_count components ($singleton_count singletons)"
done
}
# Help function
show_help() {
cat << EOF
Dynamic qmldir Generator for Quickshell
USAGE:
$(basename "$0") [QUICKSHELL_DIR]
ARGUMENTS:
QUICKSHELL_DIR Path to quickshell configuration directory
Default: \$HOME/.config/quickshell/ii
DESCRIPTION:
This script automatically generates qmldir files for quickshell configurations
by scanning for QML files and registering them appropriately. This ensures
that all components are properly registered and available for import.
The script handles:
- Root level components (ReloadPopup, etc.)
- Module components (bar, overview, etc.)
- Service components
- Nested subdirectories (functions, widgets, etc.)
- Automatic singleton detection via "pragma Singleton"
- Complex nested directory structures (qs/modules/common/functions)
Singleton Detection:
The script automatically detects QML files with "pragma Singleton" declarations
and registers them with the "singleton" keyword in qmldir files. This is
essential for proper Material You theming and service registration.
EXAMPLES:
# Generate for default location
$(basename "$0")
# Generate for custom location
$(basename "$0") /path/to/quickshell/config
# Use in automation
$(basename "$0") && quickshell -c ii
EOF
}
# Parse arguments
case "${1:-}" in
-h|--help)
show_help
exit 0
;;
*)
main "$@"
;;
esac
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/env bash
# Quickshell reset script for end-4-flakes
# This script resets quickshell and regenerates qmldir files
set -e
# Colors for output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
log() {
echo -e "${GREEN}[quickshell-reset]${NC} $1"
}
warn() {
echo -e "${YELLOW}[quickshell-reset]${NC} WARNING: $1"
}
error() {
echo -e "${RED}[quickshell-reset]${NC} ERROR: $1"
}
log "Starting quickshell reset..."
# Kill any running quickshell processes
log "Stopping quickshell processes..."
pkill -f quickshell || true
pkill -f qs || true
# Wait a moment for processes to stop
sleep 1
# Regenerate qmldir files if the generator exists
if command -v generate-qmldir >/dev/null 2>&1; then
if [[ -d "$HOME/.config/quickshell/ii" ]]; then
log "Regenerating qmldir files..."
generate-qmldir "$HOME/.config/quickshell/ii"
log "qmldir files regenerated successfully"
else
warn "Quickshell config directory not found, skipping qmldir generation"
fi
else
warn "qmldir generator not found in PATH, skipping regeneration"
fi
# Clear any cached QML modules
log "Clearing QML cache..."
rm -rf "$HOME/.cache/quickshell" 2>/dev/null || true
rm -rf "$HOME/.cache/qml" 2>/dev/null || true
# Using quickshell directly (no wrapper script needed)
log "Using quickshell directly"
log "Quickshell reset complete!"
log "You can now start quickshell with: qs"
+35
View File
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
echo "🧪 Testing dots-hyprland Python environment..."
VENV_PATH="$HOME/.local/state/quickshell/.venv"
if [[ ! -d "$VENV_PATH" ]]; then
echo "❌ Virtual environment not found at $VENV_PATH"
echo "💡 Run: home-manager switch"
exit 1
fi
source "$VENV_PATH/bin/activate"
python -c "
import sys
print(f'✅ Python {sys.version}')
try:
import material_color_utilities
print('✅ material-color-utilities')
except ImportError:
print('❌ material-color-utilities')
try:
import materialyoucolor
print('✅ materialyoucolor')
except ImportError:
print('❌ materialyoucolor')
try:
import pywayland
print('✅ pywayland')
except ImportError:
print('❌ pywayland')
"
deactivate
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
echo "🧪 Testing quickshell with dots-hyprland config..."
if [[ ! -d "$HOME/.config/quickshell" ]]; then
echo "❌ No quickshell configuration found"
echo "💡 Run: home-manager switch"
exit 1
fi
cd "$HOME/.config/quickshell"
echo "🚀 Starting quickshell (timeout 10s)..."
timeout 10 quickshell 2>&1 | head -20
+178
View File
@@ -0,0 +1,178 @@
#!/usr/bin/env bash
# dots-hyprland Flake Update Utility
# Manages flake input updates for self-contained installer replication
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
log() {
echo -e "${GREEN}[update-flake]${NC} $1"
}
warn() {
echo -e "${YELLOW}[update-flake]${NC} WARNING: $1"
}
error() {
echo -e "${RED}[update-flake]${NC} ERROR: $1"
exit 1
}
info() {
echo -e "${BLUE}[update-flake]${NC} $1"
}
header() {
echo -e "${CYAN}=== $1 ===${NC}"
}
show_help() {
cat << EOF
dots-hyprland Flake Update Utility (Self-Contained)
USAGE:
update-flake [OPTIONS] [COMMAND]
COMMANDS:
update Update all flake inputs (default)
status Show current flake input status
verify Verify flake builds after update
help Show this help message
OPTIONS:
--auto-verify Automatically verify builds after update
--dry-run Show what would be done without executing
EXAMPLES:
update-flake # Update all inputs
update-flake status # Show current status
update-flake update --auto-verify # Update and verify builds
NOTE: This flake is now self-contained and doesn't depend on external
dots-hyprland repository. All configs are included locally.
EOF
}
get_current_commit() {
git rev-parse HEAD
}
get_current_branch() {
git branch --show-current
}
show_status() {
header "Flake Status"
local current_commit=$(get_current_commit)
local current_branch=$(get_current_branch)
echo "📁 Project Directory: $(pwd)"
echo "🌿 Current Branch: $current_branch"
echo "📝 Current Commit: ${current_commit:0:12}..."
echo "🎯 Mode: Self-contained (no external dependencies)"
echo ""
log "✅ Flake is self-contained with local configs"
info "All dots-hyprland configurations are included in ./configs/"
}
update_all_inputs() {
header "Updating All Flake Inputs"
log "Running nix flake update..."
if nix flake update; then
log "✅ All inputs updated successfully"
info "Updated: nixpkgs, home-manager, quickshell"
else
error "Failed to update flake inputs"
fi
}
verify_builds() {
header "Verifying Flake Builds"
local configs=("declarative" "writable")
local success=true
for config in "${configs[@]}"; do
info "🔨 Testing $config configuration..."
if nix build ".#homeConfigurations.$config.activationPackage" --no-link --quiet; then
log "$config configuration builds successfully"
else
error "$config configuration failed to build"
success=false
fi
done
if $success; then
log "🎉 All configurations build successfully!"
else
error "Some configurations failed to build"
fi
}
# Parse command line arguments
AUTO_VERIFY=false
DRY_RUN=false
COMMAND="update"
while [[ $# -gt 0 ]]; do
case $1 in
--auto-verify)
AUTO_VERIFY=true
shift
;;
--dry-run)
DRY_RUN=true
shift
;;
update|status|verify|help)
COMMAND="$1"
shift
;;
*)
if [[ "$1" != -* ]]; then
COMMAND="$1"
shift
else
error "Unknown option: $1"
fi
;;
esac
done
# Main execution
case "$COMMAND" in
help)
show_help
;;
status)
show_status
;;
update)
if $DRY_RUN; then
info "DRY RUN: Would update all flake inputs"
show_status
else
update_all_inputs
if $AUTO_VERIFY; then
verify_builds
fi
fi
;;
verify)
verify_builds
;;
*)
show_help
;;
esac