#!/usr/bin/env bash set -euo pipefail plugin_id=io.github.rawritude.floating-mode config_home="${XDG_CONFIG_HOME:-$HOME/.config}" data_home="${XDG_DATA_HOME:-$HOME/.local/share}" state_home="${XDG_STATE_HOME:-$HOME/.local/state}/omarchy-floating-mode" plugin_dir="$config_home/omarchy/plugins/$plugin_id" hypr_dir="$config_home/hypr" module_file="$hypr_dir/floating-mode.lua" hyprland_file="$hypr_dir/hyprland.lua" require_line='require("hypr.floating-mode")' snap_source="$plugin_dir/contrib/aero-snap" snap_install_dir="$data_home/omarchy-floating-mode" current_uid="$(id -u)" account_name="$(id -un "$current_uid")" [[ "$account_name" =~ ^[A-Za-z_][A-Za-z0-9_.-]*\$?$ && "$account_name" != "." && "$account_name" != ".." ]] || { echo "The current uid does not resolve to a safe account name." >&2 exit 1 } cache_dir="/var/cache/hyprpm/$account_name/hyprland-plugins" cache_plugin="$cache_dir/hyprbars.so" cache_state="$cache_dir/state.toml" backup_plugin="$state_home/hyprbars.so.official" enabled_state="$state_home/hyprbars-was-enabled" abi_state="$state_home/native-abi" post_update_hook="$config_home/omarchy/hooks/post-update.d/$plugin_id" build_dir="" auto_rebuild=false case "${1:-}" in --auto-rebuild) auto_rebuild=true ;; --uninstall|"") ;; *) echo "usage: install-hyprbars [--auto-rebuild|--uninstall]" >&2; exit 2 ;; esac cleanup() { [[ -z "$build_dir" ]] || rm -rf -- "$build_dir" } trap cleanup EXIT require_commands() { local command_name missing=0 for command_name in "$@"; do if ! command -v "$command_name" >/dev/null 2>&1; then printf 'Missing required command: %s\n' "$command_name" >&2 missing=1 fi done ((missing == 0)) || { echo "Install the missing build tools and run this installer again." >&2 exit 1 } } hyprbars_is_enabled() { hyprpm list 2>/dev/null \ | sed $'s/\033\[[0-9;]*m//g' \ | awk '/Plugin hyprbars/{found=1; next} found && /enabled:/{print ($0 ~ /true/) ? "true" : "false"; exit}' \ | grep -qx true } if [[ "${1:-}" == "--uninstall" ]]; then require_commands hyprctl hyprpm sudo install sed grep gcc mktemp build_dir="$(mktemp -d)" gcc -O2 -Wall -Wextra -Werror "$plugin_dir/contrib/safe-cache-install.c" -o "$build_dir/safe-cache-install" if [[ -f "$hyprland_file" ]]; then sed -i '\|^require("hypr\.floating-mode")$|d' "$hyprland_file" fi rm -f "$module_file" hyprpm disable hyprbars >/dev/null 2>&1 || true if [[ -f "$backup_plugin" ]]; then sudo "$build_dir/safe-cache-install" "$current_uid" "$backup_plugin" fi if [[ -f "$enabled_state" ]] && grep -qx true "$enabled_state"; then hyprpm enable hyprbars fi hyprctl reload hyprctl configerrors rm -f -- "$snap_install_dir"/omarchy-windows-snap-*.so rmdir "$snap_install_dir" 2>/dev/null || true rm -f "$backup_plugin" "$enabled_state" rm -f "$abi_state" "$post_update_hook" rmdir "$(dirname "$post_update_hook")" 2>/dev/null || true rmdir "$state_home" 2>/dev/null || true echo "Removed Floating Mode's snapping and titlebar integrations, then restored the original hyprbars module." exit 0 fi require_commands Hyprland hyprctl hyprpm jq git make cmake cpio pkg-config g++ gcc sudo install sed grep mktemp awk sha256sum cut [[ -f "$plugin_dir/contrib/hyprbars.lua" ]] || { echo "Run this from an installed $plugin_id plugin." >&2 exit 1 } [[ -f "$snap_source/main.cpp" && -f "$snap_source/geometry.hpp" && -f "$snap_source/Makefile" && -f "$plugin_dir/contrib/safe-cache-install.c" ]] || { echo "Missing bundled Aero Snap source." >&2 exit 1 } [[ -f "$hyprland_file" ]] || { echo "Missing $hyprland_file" >&2; exit 1; } if ! hyprpm list 2>/dev/null | grep -q 'Plugin hyprbars'; then hyprpm add https://github.com/hyprwm/hyprland-plugins 7644cecdb947060682891a0db2a0cdc5c0b9e704 fi # Fetch, detach, and verify the literal reviewed commit before executing source. build_dir="$(mktemp -d)" gcc -O2 -Wall -Wextra -Werror "$plugin_dir/contrib/safe-cache-install.c" -o "$build_dir/safe-cache-install" git -C "$build_dir" init --quiet hyprland-plugins git -C "$build_dir/hyprland-plugins" remote add origin https://github.com/hyprwm/hyprland-plugins git -C "$build_dir/hyprland-plugins" fetch --depth 1 origin 7644cecdb947060682891a0db2a0cdc5c0b9e704 \ && git -C "$build_dir/hyprland-plugins" checkout --detach 7644cecdb947060682891a0db2a0cdc5c0b9e704 \ && test "$(git -C "$build_dir/hyprland-plugins" rev-parse HEAD)" = 7644cecdb947060682891a0db2a0cdc5c0b9e704 \ && git -C "$build_dir/hyprland-plugins" apply "$plugin_dir/patches/hyprbars-button-hover.patch" \ && git -C "$build_dir/hyprland-plugins" apply "$plugin_dir/patches/hyprbars-disabled-input.patch" \ && make -C "$build_dir/hyprland-plugins/hyprbars" make -C "$snap_source" BUILD_DIR="$build_dir/aero-snap" test all snap_binary_sha256="$(sha256sum "$build_dir/aero-snap/omarchy-windows-snap.so" | cut -d' ' -f1)" snap_filename="omarchy-windows-snap-${snap_binary_sha256:0:16}.so" snap_plugin="$snap_install_dir/$snap_filename" [[ ! "$snap_plugin" =~ [[:cntrl:]] && "$snap_plugin" != *']====]'* ]] || { echo "The snap module path cannot be embedded in Hyprland's Lua configuration." >&2 exit 1 } snap_plugin_replacement="$(printf '%s' "$snap_plugin" | sed 's/[\\&|]/\\&/g')" mkdir -p -m 700 "$state_home" if [[ ! -f "$backup_plugin" ]]; then install -m755 "$cache_plugin" "$backup_plugin" if hyprbars_is_enabled; then printf 'true\n'; else printf 'false\n'; fi >"$enabled_state" fi hyprpm disable hyprbars >/dev/null 2>&1 || true sudo_options=() if [[ "$auto_rebuild" == true && "${OMARCHY_UPDATE_UNATTENDED:-}" == 1 ]]; then sudo_options=(-n) fi sudo "${sudo_options[@]}" "$build_dir/safe-cache-install" "$current_uid" "$build_dir/hyprland-plugins/hyprbars/hyprbars.so" hyprpm enable hyprbars hyprpm reload # HyprPM may rewrite its plugin state as root while reloading. Run the same # verified atomic install once more so both the selected module and its exact # cache metadata finish in a user-manageable state. sudo "${sudo_options[@]}" "$build_dir/safe-cache-install" "$current_uid" "$build_dir/hyprland-plugins/hyprbars/hyprbars.so" mkdir -p -m 700 "$snap_install_dir" if [[ -e "$snap_plugin" ]]; then [[ "$(sha256sum "$snap_plugin" | cut -d' ' -f1)" == "$snap_binary_sha256" ]] || { echo "Existing snap module does not match its content-addressed filename." >&2 exit 1 } else install -m755 "$build_dir/aero-snap/omarchy-windows-snap.so" "$snap_plugin" fi sed "s|@SNAP_PLUGIN_PATH@|$snap_plugin_replacement|g" "$plugin_dir/contrib/hyprbars.lua" >"$build_dir/floating-mode.lua" install -Dm644 "$build_dir/floating-mode.lua" "$module_file" grep -Fxq "$require_line" "$hyprland_file" || printf '\n%s\n' "$require_line" >>"$hyprland_file" hyprctl reload errors="$(hyprctl configerrors)" printf '%s\n' "$errors" [[ -z "$errors" ]] || exit 1 installed_abi="$(Hyprland --version-json | jq -er '.abiHash | select(type == "string" and length > 0 and length <= 256)')" \ || { echo "Unable to determine the installed Hyprland ABI." >&2; exit 1; } printf '%s\n' "$installed_abi" >"$abi_state" install -Dm755 "$plugin_dir/contrib/rebuild-after-update" "$post_update_hook" for installed_snap in "$snap_install_dir"/omarchy-windows-snap-*.so; do [[ "$installed_snap" == "$snap_plugin" || ! -e "$installed_snap" ]] || rm -f -- "$installed_snap" done echo "Installed native Floating Mode titlebars, magnetic snapping, and Aero-style snap zones."