quickshell and hyprland additions

This commit is contained in:
2026-03-15 13:56:00 +02:00
parent c9c27d1554
commit 1ad06b82a6
509 changed files with 68371 additions and 19 deletions

View File

@@ -0,0 +1,118 @@
#!/bin/bash
# List desktop applications for the launcher
# from github.com/bgibson72/yahr-quickshell with modifications
# Blacklist - apps to hide (add desktop file basenames here)
BLACKLIST=(
"xfce4-about.desktop"
"avahi-discover.desktop"
"bssh.desktop"
"bvnc.desktop"
"qv4l2.desktop"
"qvidcap.desktop"
"lstopo.desktop"
"uuctl.desktop"
"codium.desktop" # Hide regular VSCodium (keep Wayland version)
"xgps.desktop" # Hide Xgps
"xgpsspeed.desktop" # Hide Xgpsspeed
)
# Whitelist - always include these desktop files
WHITELIST=(
"wallpaper.desktop"
"theme.desktop"
"powermenu.desktop"
)
# Search paths for .desktop files (local first so overrides work)
SEARCH_PATHS=(
"$HOME/.local/share/applications"
"$HOME/.local/share/flatpak/exports/share/applications"
"/var/lib/flatpak/exports/share/applications"
"/usr/local/share/applications"
"/usr/share/applications"
)
# Function to find icon path
find_icon() {
local icon_name="$1"
local theme="Papirus"
icon_name="${icon_name#theme://}"
[[ "$icon_name" == /* ]] && { echo "$icon_name"; return; }
local exts=(png svg xpm)
local sizes=(16 22 24 32 48 64 128 256 512 scalable)
local icon_bases=(
"$HOME/.local/share/icons/$theme"
"/usr/share/icons/$theme"
"/usr/share/icons/hicolor"
"/usr/share/pixmaps"
)
for base in "${icon_bases[@]}"; do
for size in "${sizes[@]}"; do
for ext in "${exts[@]}"; do
for subdir in apps actions status devices places panel mimetypes; do
local candidate="$base/${size}x${size}/$subdir/$icon_name.$ext"
[[ -f "$candidate" ]] && { echo "$candidate"; return; }
done
local scalable="$base/scalable/apps/$icon_name.$ext"
[[ -f "$scalable" ]] && { echo "$scalable"; return; }
done
done
done
for ext in "${exts[@]}"; do
[[ -f "/usr/share/pixmaps/$icon_name.$ext" ]] && { echo "/usr/share/pixmaps/$icon_name.$ext"; return; }
done
echo "$icon_name"
}
# Collect all desktop files and process
declare -A seen_apps
for dir in "${SEARCH_PATHS[@]}"; do
[ ! -d "$dir" ] && continue
while IFS= read -r desktop_file; do
basename_file=$(basename "$desktop_file")
# Skip duplicates (local overrides system)
[[ -n "${seen_apps[$basename_file]}" ]] && continue
seen_apps[$basename_file]=1
# Skip blacklisted unless whitelisted
skip=0
for blacklisted in "${BLACKLIST[@]}"; do
[[ "$basename_file" == "$blacklisted" ]] && skip=1 && break
done
# Check whitelist override
for whitelisted in "${WHITELIST[@]}"; do
[[ "$basename_file" == "$whitelisted" ]] && skip=0 && break
done
[[ $skip -eq 1 ]] && continue
# Skip if NoDisplay=true
grep -q "^NoDisplay=true" "$desktop_file" 2>/dev/null && continue
# Extract fields
name=$(grep "^Name=" "$desktop_file" | head -1 | cut -d= -f2-)
comment=$(grep "^Comment=" "$desktop_file" | head -1 | cut -d= -f2-)
icon=$(grep "^Icon=" "$desktop_file" | head -1 | cut -d= -f2-)
exec=$(grep "^Exec=" "$desktop_file" | head -1 | cut -d= -f2- | sed 's/%[uUfF]//g' | sed 's/%[cdnNvmki]//g')
# Skip if no name or exec
[ -z "$name" ] && continue
[ -z "$exec" ] && continue
# Default comment
[ -z "$comment" ] && comment="Application"
# Find icon
icon_path=$(find_icon "$icon")
# Output
echo "$name|$comment|$icon_path|$exec"
done < <(find -L "$dir" -name "*.desktop" -type f 2>/dev/null)
done | sort -u

View File

@@ -0,0 +1,33 @@
#!/bin/bash
START_DIR="$HOME/Pictures/Wallpapers"
# Get monitor list (Wayland/Hyprland/Qtile etc. usually expose via xrandr or hyprctl)
MONITORS=$(xrandr --query | grep " connected" | cut -d" " -f1)
# Convert monitors into Zenity list arguments
LIST_ARGS=()
for m in $MONITORS; do
LIST_ARGS+=("$m")
done
DISPLAY=$(zenity --list \
--title="Select Display" \
--column="Monitor" \
"${LIST_ARGS[@]}" \
--height=300 \
--width=300 2>/dev/null)
# User cancelled
[ -z "$DISPLAY" ] && echo "null" && exit
FILE=$(zenity --file-selection \
--title="Select Wallpaper for $DISPLAY" \
--filename="$START_DIR/" \
--file-filter="Images/Videos | *.png *.jpg *.jpeg *.webp *.bmp *.svg *.mp4 *.mkv *.webm *.mov *.avi *.m4v" \
2>/dev/null)
[ -z "$FILE" ] && echo "null" && exit
# Output format: monitor|wallpaper
echo "$DISPLAY|file://$FILE"

View File

@@ -0,0 +1,66 @@
#!/bin/bash
# ~/config/quickshell/scripts/background/gencolors.sh
# Generate Matugen color scheme for a given wallpaper
USER_WIDE=false
# Parse flags
while [[ "$1" == --* ]]; do
case "$1" in
--user-wide)
USER_WIDE=true
shift
;;
*)
echo "Unknown flag: $1" >&2
exit 1
;;
esac
done
WALLPAPER_PATH="$1"
SCHEME_TYPE="$2"
SCHEME_MODE="$3"
CONFIG_PATH="$4"
# Validate required arguments
if [[ -z "$WALLPAPER_PATH" || "$WALLPAPER_PATH" == "null" ]]; then
echo "Error: no wallpaper provided" >&2
exit 1
fi
: "${SCHEME_TYPE:?Error: scheme type not provided}"
: "${SCHEME_MODE:?Error: scheme mode not provided}"
# Strip file:// prefix if present
if [[ "$WALLPAPER_PATH" == file://* ]]; then
WALLPAPER_PATH="${WALLPAPER_PATH#file://}"
fi
if ! $USER_WIDE; then
if [[ -z "$CONFIG_PATH" || ! -f "$CONFIG_PATH" ]]; then
echo "Error: config file not found: $CONFIG_PATH" >&2
exit 1
fi
fi
run_with_config() {
matugen --config "$CONFIG_PATH" \
image "$WALLPAPER_PATH" \
--type "$SCHEME_TYPE" \
--mode "$SCHEME_MODE"
}
run_without_config() {
matugen image "$WALLPAPER_PATH" \
--type "$SCHEME_TYPE" \
--mode "$SCHEME_MODE"
}
if $USER_WIDE; then
run_with_config
run_without_config
else
run_with_config
fi

View File

@@ -0,0 +1,24 @@
#!/bin/bash
# Folder selector for wallpaper slideshow
START_DIR="${1:-$HOME/Pictures/Wallpapers}"
# Ensure start dir exists, fallback to Pictures or Home
if [ ! -d "$START_DIR" ]; then
START_DIR="$HOME/Pictures"
fi
if [ ! -d "$START_DIR" ]; then
START_DIR="$HOME"
fi
FOLDER=$(zenity --file-selection \
--directory \
--title="Select Wallpaper Folder" \
--filename="$START_DIR/" 2>/dev/null)
if [ $? -eq 0 ] && [ -n "$FOLDER" ]; then
echo "$FOLDER"
else
echo "null"
fi

View File

@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -euo pipefail
THEME_NAME="${1:-}"
THEME_DIR="$HOME/.config/nucleus-shell/colorschemes"
TARGET="$HOME/.config/nucleus-shell/config/colors.json"
if [[ -z "$THEME_NAME" ]]; then
echo "Usage: switch-theme.sh <theme-name | auto>"
exit 1
fi
# === AUTOGENERATED THEME ===
if [[ "$THEME_NAME" == "auto" || "$THEME_NAME" == "autogen" ]]; then
echo "Generating theme via Quickshell IPC…"
qs -c nucleus-shell ipc call global regenColors
echo "Autogenerated theme applied"
exit 0
fi
# === STATIC THEME ===
SOURCE="$THEME_DIR/$THEME_NAME.json"
if [[ ! -f "$SOURCE" ]]; then
echo "Theme not found: $THEME_NAME"
exit 1
fi
# Atomic write
tmp="$(mktemp)"
cat "$SOURCE" > "$tmp"
mv "$tmp" "$TARGET"
echo "Theme switched to: $THEME_NAME"

View File

@@ -0,0 +1,242 @@
#!/usr/bin/env bash
set -euo pipefail
# This script the now depreciated as it is succeeded by the nucleus-cli (https://github.com/unf6/nucleus-cli)
# Config
INSTALL_DIR="$HOME/.config/nucleus-shell/plugins"
CACHE_BASE="/tmp/nucleus-plugins"
declare -A PLUGIN_REPOS=(
[official]="https://github.com/xZepyx/nucleus-plugins.git"
)
# Dependencies
require() {
command -v "$1" >/dev/null 2>&1 || {
echo "Missing dependency: $1"
exit 1
}
}
require git
require jq
mkdir -p "$INSTALL_DIR" "$CACHE_BASE"
# Repo handling
update_repo() {
local name="$1"
local url="$2"
local dir="$CACHE_BASE/$name"
if [[ -d "$dir/.git" ]]; then
git -C "$dir" pull --quiet
else
rm -rf "$dir"
git clone --quiet "$url" "$dir"
fi
}
update_all_repos() {
for name in "${!PLUGIN_REPOS[@]}"; do
update_repo "$name" "${PLUGIN_REPOS[$name]}"
done
}
# Plugin Lookup
find_plugin() {
local plugin="$1"
for repo in "${!PLUGIN_REPOS[@]}"; do
local path="$CACHE_BASE/$repo/$plugin"
if [[ -d "$path" && -f "$path/manifest.json" ]]; then
echo "$repo:$path"
return 0
fi
done
return 1
}
# Fetch
fetch_all() {
update_all_repos
for repo in "${!PLUGIN_REPOS[@]}"; do
local base="$CACHE_BASE/$repo"
for dir in "$base"/*/; do
[[ -f "$dir/manifest.json" ]] || continue
jq -r '
"id: \(.id)
name: \(.name)
version: \(.version)
author: \(.author)
description: \(.description)
requires_nucleus: \(.requires_nucleus // "none")
repo: '"$repo"'
---"
' "$dir/manifest.json"
done
done
}
fetch_one() {
local plugin="$1"
update_all_repos
local result
result=$(find_plugin "$plugin") || {
echo "Plugin '$plugin' not found in any repo"
exit 1
}
local repo="${result%%:*}"
local path="${result#*:}"
jq -r '
"id: \(.id)
name: \(.name)
version: \(.version)
author: \(.author)
description: \(.description)
requires_nucleus: \(.requires_nucleus // "none")
repo: '"$repo"'
---"
' "$path/manifest.json"
}
# Install / Update / Uninstall
install_plugin() {
local plugin="$1"
update_all_repos
local dst="$INSTALL_DIR/$plugin"
[[ -d "$dst" ]] && {
echo "Plugin '$plugin' already installed"
exit 0
}
local result
result=$(find_plugin "$plugin") || {
echo "Plugin '$plugin' not found"
exit 1
}
local path="${result#*:}"
cp -r "$path" "$dst"
echo "Installed plugin '$plugin'"
}
uninstall_plugin() {
local plugin="$1"
local dst="$INSTALL_DIR/$plugin"
[[ -d "$dst" ]] || {
echo "Plugin '$plugin' is not installed"
exit 0
}
rm -rf "$dst"
echo "Uninstalled plugin '$plugin'"
}
fetch_all_machine() { # For quickshell
update_all_repos
for repo in "${!PLUGIN_REPOS[@]}"; do
local base="$CACHE_BASE/$repo"
for dir in "$base"/*/; do
[[ -f "$dir/manifest.json" ]] || continue
jq -r '
[
.id,
.name,
.version,
.author,
.description,
(.requires_nucleus // "none"),
"'"$repo"'"
] | @tsv
' "$dir/manifest.json"
done
done
}
update_plugin() {
local plugin="$1"
update_all_repos
local dst="$INSTALL_DIR/$plugin"
[[ -d "$dst" ]] || {
echo "Plugin '$plugin' not installed"
exit 1
}
local result
result=$(find_plugin "$plugin") || {
echo "Plugin '$plugin' not found in repos"
exit 1
}
local src="${result#*:}"
local local_version repo_version
local_version=$(jq -r '.version' "$dst/manifest.json")
repo_version=$(jq -r '.version' "$src/manifest.json")
if [[ "$local_version" == "$repo_version" ]]; then
echo "Plugin '$plugin' already up to date ($local_version)"
exit 0
fi
rm -rf "$dst"
cp -r "$src" "$dst"
echo "Updated '$plugin' $local_version$repo_version"
}
# CLI
usage() {
cat <<EOF
Usage:
plugins fetch all
plugins fetch <pluginId>
plugins install <pluginId>
plugins uninstall <pluginId>
plugins update <pluginId>
EOF
}
case "${1:-}" in
fetch)
[[ "${2:-}" == "all-machine" ]] && fetch_all_machine \
|| [[ "${2:-}" == "all" ]] && fetch_all \
|| fetch_one "${2:-}"
;;
install)
install_plugin "${2:-}"
;;
uninstall)
uninstall_plugin "${2:-}"
;;
update)
update_plugin "${2:-}"
;;
*)
usage
;;
esac

View File

@@ -0,0 +1,4 @@
#!/bin/bash
killall quickshell
nucleus run

View File

@@ -0,0 +1,126 @@
#!/usr/bin/env bash
set -Eeuo pipefail
# Paths / repo
CONFIG="$HOME/.config/nucleus-shell/config/configuration.json"
QS_DIR="$HOME/.config/quickshell/nucleus-shell"
REPO="xZepyx/nucleus-shell"
API="https://api.github.com/repos/$REPO/releases"
# Spinner
spinner() {
local pid=$1
local spin='|/-\'
local i=0
while kill -0 "$pid" 2>/dev/null; do
printf "\r[*] %s %c" "$SPINNER_MSG" "${spin:i++%4:1}"
sleep 0.1
done
}
run() {
SPINNER_MSG="$1"
shift
"$@" &>/dev/null &
spinner $!
wait $! || fail "$SPINNER_MSG failed"
printf "\r[✓] %s\n" "$SPINNER_MSG"
}
fail() {
printf "[✗] %s\n" "$1" >&2
exit 1
}
info() {
printf "[*] %s\n" "$1"
}
# Selection
echo "Select the version to install:"
echo "1. Latest"
echo "2. Edge"
echo "3. Git"
read -rp "[?] Choice: " choice
case "$choice" in
1) mode="stable" ;;
2) mode="indev" ;;
3)
read -rp "[?] Enter git tag or version: " input
[[ -z "$input" ]] && fail "No version provided"
latest="${input#v}"
latest_tag="v$latest"
;;
*) fail "Invalid choice" ;;
esac
# Validate config
[[ -f "$CONFIG" ]] || fail "configuration.json not found"
current="$(jq -r '.shell.version // empty' "$CONFIG")"
[[ -n "$current" ]] || fail "Current version not set"
# Resolve release
if [[ "${mode:-}" ]]; then
info "Resolving release"
latest_tag="$(
curl -fsSL "$API" |
jq -r "
map(select(.draft == false)) |
$( [[ "$mode" == "stable" ]] && echo 'map(select(.prerelease == false)) |' )
sort_by(.published_at) |
last |
.tag_name
"
)"
[[ -n "$latest_tag" && "$latest_tag" != "null" ]] || fail "Release resolution failed"
latest="${latest_tag#v}"
fi
# No-op
if [[ "$current" == "$latest" ]]; then
info "Already up to date ($current)"
exit 0
fi
# Temp workspace
tmp="$(mktemp -d)"
zip="$tmp/source.zip"
root_dir="$tmp/nucleus-shell-$latest"
SRC_DIR="$root_dir/quickshell/nucleus-shell"
# Download
run "Downloading nucleus-shell $latest" \
curl -fsSL \
"https://github.com/$REPO/archive/refs/tags/$latest_tag.zip" \
-o "$zip"
# Extract
run "Extracting archive" unzip -q "$zip" -d "$tmp"
[[ -d "$SRC_DIR" ]] || fail "nucleus-shell directory missing in archive"
# Install
run "Installing files" bash -c "
rm -rf '$QS_DIR' &&
mkdir -p '$QS_DIR' &&
cp -r '$SRC_DIR/'* '$QS_DIR/'
"
# Update config
run "Updating configuration" bash -c "
tmp_cfg=\$(mktemp) &&
jq --arg v '$latest' '.shell.version = \$v' '$CONFIG' > \"\$tmp_cfg\" &&
mv \"\$tmp_cfg\" '$CONFIG'
"
# Reload shell
run "Reloading shell" bash -c "
killall qs &>/dev/null || true
nohup qs -c nucleus-shell &>/dev/null & disown
"
printf "[✓] Updated nucleus-shell: %s -> %s\n" "$current" "$latest"