aboutsummaryrefslogtreecommitdiffstats
path: root/config/hypr/scripts/ToggleOpacity.sh
blob: d44249d715985dc86cc010bb41b9e0051599099b (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
#!/usr/bin/env bash
# ==================================================
#  KoolDots (2026)
#  Project URL: https://github.com/LinuxBeginnings
#  License: GNU GPLv3
#  SPDX-License-Identifier: GPL-3.0-or-later
# ==================================================
# Toggle or incrementally adjust active window opacity with desktop notifications.
# Supports cycling preset levels (100% -> 85% -> 70% -> 50% -> 100%),
# stepping up/down (--inc / --dec), or setting explicit values.
# Uses flock to prevent double-execution from dual-config (.conf + .lua) loading.

set -uo pipefail

LOCK="/tmp/.hypr_toggle_opacity_${HYPRLAND_INSTANCE_SIGNATURE:-default}.lock"
STEP=0.05
MIN_OPACITY=0.20
MAX_OPACITY=1.00

config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
hypr_dir="$config_home/hypr"
lua_entry="$hypr_dir/hyprland.lua"
legacy_lua_entry="$config_home/hyprland.lua"

if [[ -f "$lua_entry" || -f "$legacy_lua_entry" ]]; then
    hypr_config_mode="lua"
else
    hypr_config_mode="conf"
fi

icons_dir="$config_home/swaync/icons"
images_dir="$config_home/swaync/images"

if [[ -f "$icons_dir/palette.png" ]]; then
    ICON="$icons_dir/palette.png"
elif [[ -f "$icons_dir/dropper.png" ]]; then
    ICON="$icons_dir/dropper.png"
elif [[ -f "$images_dir/note.png" ]]; then
    ICON="$images_dir/note.png"
else
    ICON="$images_dir/ja.png"
fi

(
  flock -n 200 || exit 0

  # Get active window info
  ACTIVE_JSON=$(hyprctl activewindow -j 2>/dev/null || true)
  ACTIVE_CLASS=""
  if [[ -n "$ACTIVE_JSON" ]]; then
    ACTIVE_CLASS=$(echo "$ACTIVE_JSON" | jq -r '.class // empty' 2>/dev/null || true)
  fi

  CURRENT_PROP=$(hyprctl getprop active opacity 2>/dev/null || true)
  CURRENT_OPAQUE=$(hyprctl getprop active opaque 2>/dev/null || true)

  CURRENT_VAL=""
  if [[ -n "$CURRENT_PROP" && "$CURRENT_PROP" != *"not found"* && "$CURRENT_PROP" != *"unknown"* ]]; then
    CURRENT_VAL=$(echo "$CURRENT_PROP" | awk '{v = $1; if (v ~ /^[0-9.]+$/) print v;}')
  fi

  if [[ -z "$CURRENT_VAL" ]]; then
    CURRENT_VAL=$(hyprctl -j getoption decoration:active_opacity 2>/dev/null | jq -r '.float // empty')
  fi
  if [[ -z "$CURRENT_VAL" || "$CURRENT_VAL" == "null" ]]; then
    CURRENT_VAL=$(hyprctl getoption decoration:active_opacity 2>/dev/null | awk 'NR==1{print $2}')
  fi

  # Fallback to 1.0 if detection was empty
  CURRENT_NUM=$(awk -v c="${CURRENT_VAL:-1.0}" 'BEGIN { v = c + 0; if (v <= 0 || v > 1.0) v = 1.0; printf "%.2f", v }')

  # If window is explicitly opaque property true, consider it 1.0
  if [[ "${CURRENT_OPAQUE:-false}" == "true" ]]; then
    CURRENT_NUM="1.00"
  fi

  ACTION="${1:---toggle}"

  case "$ACTION" in
    --inc|+|-inc|inc|up|--up)
      TARGET_NUM=$(awk -v c="$CURRENT_NUM" -v s="$STEP" -v max="$MAX_OPACITY" 'BEGIN {
        v = c + s;
        if (v > max) v = max;
        printf "%.2f", v;
      }')
      ;;
    --dec|-|-dec|dec|down|--down)
      TARGET_NUM=$(awk -v c="$CURRENT_NUM" -v s="$STEP" -v min="$MIN_OPACITY" 'BEGIN {
        v = c - s;
        if (v < min) v = min;
        printf "%.2f", v;
      }')
      ;;
    --toggle|toggle|"")
      # Cycle through predefined incremental levels: 1.00 -> 0.85 -> 0.70 -> 0.50 -> 1.00
      TARGET_NUM=$(awk -v c="$CURRENT_NUM" 'BEGIN {
        if (c >= 0.98)      printf "0.85";
        else if (c >= 0.80) printf "0.70";
        else if (c >= 0.65) printf "0.50";
        else                printf "1.00";
      }')
      ;;
    *)
      # Parse explicit number / percentage, e.g. 0.85 or 85 or 85%
      RAW_ARG="${ACTION#--}"
      RAW_ARG="${RAW_ARG%\%}"
      TARGET_NUM=$(awk -v a="$RAW_ARG" -v min="$MIN_OPACITY" -v max="$MAX_OPACITY" 'BEGIN {
        v = a + 0;
        if (v > 1.0) v = v / 100.0;
        if (v > max) v = max;
        if (v < min) v = min;
        printf "%.2f", v;
      }')
      ;;
  esac

  TARGET_PROP="${TARGET_NUM} ${TARGET_NUM}"
  PERCENT=$(awk -v v="$TARGET_NUM" 'BEGIN { printf "%d", (v * 100) + 0.5 }')

  if [ "$PERCENT" -ge 99 ]; then
    OPAQUE_ACTION="true"
    DISPLAY_MSG="100% (Opaque)"
  else
    OPAQUE_ACTION="false"
    DISPLAY_MSG="${PERCENT}%"
  fi

  if [[ "$hypr_config_mode" == "lua" ]]; then
    # Set window-level property so it affects the active window even when windowrules are active
    hyprctl eval "return hl.dispatch(hl.dsp.window.set_prop({ prop = 'opacity', value = '${TARGET_PROP}' }))" >/dev/null 2>&1 || true
    hyprctl eval "return hl.dispatch(hl.dsp.window.set_prop({ prop = 'opaque', value = '${OPAQUE_ACTION}' }))" >/dev/null 2>&1 || true
    # Also update global active_opacity config
    hyprctl eval "hl.config({ decoration = { active_opacity = ${TARGET_NUM} } })" >/dev/null 2>&1 || true
  else
    hyprctl dispatch setprop active opacity "$TARGET_PROP" >/dev/null 2>&1 || true
    hyprctl dispatch setprop active opaque "$OPAQUE_ACTION" >/dev/null 2>&1 || true
    hyprctl keyword decoration:active_opacity "$TARGET_NUM" >/dev/null 2>&1 || true
  fi

  # Send notification
  if command -v notify-send >/dev/null 2>&1 && [[ -n "${WAYLAND_DISPLAY:-}${DISPLAY:-}" ]]; then
    SUBTITLE="${ACTIVE_CLASS:-Active Window}"
    notify-send -e \
      -h string:x-canonical-private-synchronous:opacity_notif \
      -h int:value:"$PERCENT" \
      -u low \
      -i "$ICON" \
      " Opacity: ${DISPLAY_MSG}" " ${SUBTITLE}" 2>/dev/null || true
  fi
) 200>"$LOCK"
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage