aboutsummaryrefslogtreecommitdiffstats
path: root/config/hypr/UserScripts/RainbowBorders.bak.sh
blob: 82807919e3219027c10dedc82fa2445e8aa446e6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#!/usr/bin/env bash
# ==================================================
#  KoolDots (2026)
#  Project URL: https://github.com/LinuxBeginnings
#  License: GNU GPLv3
#  SPDX-License-Identifier: GPL-3.0-or-later
# ==================================================
# Smooth border cycling effect using Wallust palette or full rainbow
#
# Disabled by default as RainbowBorders.bak.sh.
# Enable / choose mode via Quick Settings (SUPER SHIFT + E → Rainbow Borders Mode).
# That renames this file to RainbowBorders.sh.
#
# Under Hyprland Lua config mode, hyprctl keyword is rejected
# ("keyword can't work with non-legacy parsers"). This script falls back to:
#   hyprctl eval 'hl.config({ general = { col = { active_border = { colors = {...}, angle = N } } } })'

# Possible values: "wallust_random", "rainbow", "gradient_flow"
EFFECT_TYPE="gradient_flow"

WALLUST_COLORS_SOURCE="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallust/wallust-hyprland.conf"

WALLUST_COLORS=()

# ---------- LOAD WALLUST COLORS ----------
if [[ "$EFFECT_TYPE" == "wallust_random" || "$EFFECT_TYPE" == "gradient_flow" ]]; then
  # Accept either hex (0xffRRGGBB) or rgb(r,g,b) and normalize to 0xffRRGGBB
  mapfile -t WALLUST_COLORS < <(
    grep -E '^\$color[0-9]+' "$WALLUST_COLORS_SOURCE" | awk '
        function hex2(s){ return (length(s)==6 ? "0xff"s : ""); }
        function rgb2(r,g,b){ return sprintf("0xff%02x%02x%02x", r, g, b); }
        {
            if (match($0, /0x([0-9a-fA-F]{8})/, m)) { print "0x" m[1]; next }
            if (match($0, /#([0-9a-fA-F]{6})/, m))  { print hex2(m[1]); next }
            if (match($0, /rgb\(([0-9]+),[ ]*([0-9]+),[ ]*([0-9]+)\)/, m)) {
                print rgb2(m[1], m[2], m[3]); next
            }
        }'
  )

  if ((${#WALLUST_COLORS[@]} == 0)); then
    # If wallust colors can't be loaded, fall back to random_hex
    EFFECT_TYPE="rainbow"
  fi
fi

# ---------- RANDOM WALLUST COLORS ----------
function wallust_random() {
  echo "${WALLUST_COLORS[RANDOM % ${#WALLUST_COLORS[@]}]}"
}

# ---------- RAINBOW COLORS ----------
# Fixed spectrum so "Original Rainbow" is visibly multi-hue (not random pastels).
RAINBOW_PALETTE=(
  "0xffff0000" "0xffff8000" "0xffffff00" "0xff80ff00" "0xff00ff00"
  "0xff00ff80" "0xff00ffff" "0xff0080ff" "0xff0000ff" "0xff8000ff"
)
function random_hex() {
  # Keep name for compatibility; prefer palette entry by index when available.
  if ((${#RAINBOW_PALETTE[@]} > 0)); then
    echo "${RAINBOW_PALETTE[RANDOM % ${#RAINBOW_PALETTE[@]}]}"
    return
  fi
  echo "0xff$(openssl rand -hex 3)"
}
function rainbow_color() {
  local idx="${1:-0}"
  if ((${#RAINBOW_PALETTE[@]} > 0)); then
    echo "${RAINBOW_PALETTE[idx % ${#RAINBOW_PALETTE[@]}]}"
    return
  fi
  random_hex
}

# ---------- FLOW MODE ----------
BASE_COLOR="${WALLUST_COLORS[10]}"
GRAD1_COLOR="${WALLUST_COLORS[14]}"
GRAD2_COLOR="${WALLUST_COLORS[13]}"
GLOW_COLOR="${WALLUST_COLORS[15]}"

MAX_POS=10
GLOW_POS=0

function gradient_flow_color() {
  local pos=$1
  local d=$((pos - GLOW_POS))

  # wrap distance (-9..9)
  if ((d > MAX_POS / 2)); then d=$((d - MAX_POS)); fi
  if ((d < -MAX_POS / 2)); then d=$((d + MAX_POS)); fi

  case "${d#-}" in
  0) echo "$GLOW_COLOR" ;;
  1) echo "$GRAD1_COLOR" ;;
  2) echo "$GRAD2_COLOR" ;;
  *) echo "$BASE_COLOR" ;;
  esac

  if ((pos == MAX_POS - 1)); then
    GLOW_POS=$(((GLOW_POS + 1) % MAX_POS))
  fi
}

# ---------- Main function ----------
function get_color() {
  if [[ "$EFFECT_TYPE" == "wallust_random" && ${#WALLUST_COLORS[@]} -gt 0 ]]; then
    wallust_random
  elif [[ "$EFFECT_TYPE" == "gradient_flow" && ${#WALLUST_COLORS[@]} -ge 16 ]]; then
    gradient_flow_color "$1"
  elif [[ "$EFFECT_TYPE" == "rainbow" ]]; then
    rainbow_color "$1"
  else
    random_hex
  fi
}

# Set a gradient border option for both legacy hyprlang and Lua config modes.
# Usage: set_gradient_border general:col.active_border color0 color1 ... [angledeg]
set_gradient_border() {
  local option="$1"
  shift
  local angle="270"
  local -a colors=()
  local arg c lua_colors expr out

  for arg in "$@"; do
    if [[ "$arg" =~ ^([0-9]+)deg$ ]]; then
      angle="${BASH_REMATCH[1]}"
    else
      colors+=("$arg")
    fi
  done

  ((${#colors[@]} > 0)) || return 1

  # Legacy conf mode.
  # Note: under Lua config mode hyprctl may exit 0 while still printing
  # "keyword can't work with non-legacy parsers", so check output too.
  out="$(hyprctl keyword "$option" "${colors[@]}" "${angle}deg" 2>&1)"
  rc=$?
  if [[ $rc -eq 0 && "$out" != *"non-legacy parsers"* && "$out" != *"Use eval"* && "$out" != *"error"* && "$out" != *"invalid"* ]]; then
    return 0
  fi

  # Lua config mode rejects keyword; use hl.config via eval.
  lua_colors=""
  for c in "${colors[@]}"; do
    [[ -n "$lua_colors" ]] && lua_colors+=", "
    lua_colors+="\"${c}\""
  done

  case "$option" in
  general:col.active_border)
    expr="hl.config({ general = { col = { active_border = { colors = { ${lua_colors} }, angle = ${angle} } } } })"
    ;;
  general:col.inactive_border)
    expr="hl.config({ general = { col = { inactive_border = { colors = { ${lua_colors} }, angle = ${angle} } } } })"
    ;;
  *)
    printf '[RainbowBorders] unsupported option for Lua fallback: %s\n' "$option" >&2
    printf '[RainbowBorders] keyword error: %s\n' "$out" >&2
    return 1
    ;;
  esac

  if out="$(hyprctl eval "$expr" 2>&1)"; then
    return 0
  fi

  printf '[RainbowBorders] failed to set %s\n' "$option" >&2
  printf '[RainbowBorders] keyword error: %s\n' "$out" >&2
  printf '[RainbowBorders] eval error: %s\n' "$out" >&2
  return 1
}

# border effect for ACTIVE window
set_gradient_border general:col.active_border \
  "$(get_color 0)" "$(get_color 1)" "$(get_color 2)" "$(get_color 3)" "$(get_color 4)" \
  "$(get_color 5)" "$(get_color 6)" "$(get_color 7)" "$(get_color 8)" "$(get_color 9)" \
  270deg

# border effect for INACTIVE windows (optional)
# set_gradient_border general:col.inactive_border \
#   "$(get_color 0)" "$(get_color 1)" "$(get_color 2)" "$(get_color 3)" "$(get_color 4)" \
#   "$(get_color 5)" "$(get_color 6)" "$(get_color 7)" "$(get_color 8)" "$(get_color 9)" \
#   270deg
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage