feat: use tui for bar tools
This commit is contained in:
@@ -5,10 +5,10 @@
|
|||||||
# "center, class:^(org\.hakase\..*)$"
|
# "center, class:^(org\.hakase\..*)$"
|
||||||
# "size 80% 70%, class:^(org\.hakase\..*)$" # Example using percentages
|
# "size 80% 70%, class:^(org\.hakase\..*)$" # Example using percentages
|
||||||
# --- POPUP RULES (Wifi, BT, Audio) ---
|
# --- POPUP RULES (Wifi, BT, Audio) ---
|
||||||
"size 602 478, class:^(org\.hakase\.popup\..*)$"
|
# "size 602 478, class:^(org\.hakase\.popup\..*)$"
|
||||||
"move 1312 32, class:^(org\.hakase\.popup\..*)$"
|
# "move 1312 32, class:^(org\.hakase\.popup\..*)$"
|
||||||
"float, class:^(org\.hakase\.popup\..*)$"
|
"float, class:^(org\.hakase\.popup\..*)$"
|
||||||
"pin, class:^(org\.hakase\.popup\..*)$"
|
# "pin, class:^(org\.hakase\.popup\..*)$"
|
||||||
"animation slide right, class:^(org\.hakase\.popup\..*)$"
|
"animation slide right, class:^(org\.hakase\.popup\..*)$"
|
||||||
"dimaround, class:^(org\.hakase\.popup\..*)$"
|
"dimaround, class:^(org\.hakase\.popup\..*)$"
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -95,7 +95,7 @@
|
|||||||
tooltip-format-disconnected = "Disconnected";
|
tooltip-format-disconnected = "Disconnected";
|
||||||
interval = 3;
|
interval = 3;
|
||||||
spacing = 1;
|
spacing = 1;
|
||||||
on-click = "hakase-launch-wifi";
|
on-click = "hakase-popup-wifi";
|
||||||
};
|
};
|
||||||
|
|
||||||
"battery" = {
|
"battery" = {
|
||||||
@@ -124,12 +124,12 @@
|
|||||||
format-connected = "";
|
format-connected = "";
|
||||||
format-no-controller = "";
|
format-no-controller = "";
|
||||||
tooltip-format = "Devices connected: {num_connections}";
|
tooltip-format = "Devices connected: {num_connections}";
|
||||||
on-click = "hakase-launch-bluetooth";
|
on-click = "hakase-popup-bluetooth";
|
||||||
};
|
};
|
||||||
|
|
||||||
"pulseaudio" = {
|
"pulseaudio" = {
|
||||||
format = "{icon}";
|
format = "{icon}";
|
||||||
on-click = "hakase-focus-wrapper wiremix";
|
on-click = "hakase-popup-volume";
|
||||||
on-click-right = "pamixer -t";
|
on-click-right = "pamixer -t";
|
||||||
tooltip-format = "Playing at {volume}%";
|
tooltip-format = "Playing at {volume}%";
|
||||||
scroll-step = 5;
|
scroll-step = 5;
|
||||||
|
|||||||
+73
-47
@@ -53,71 +53,97 @@
|
|||||||
|
|
||||||
'';
|
'';
|
||||||
hakase-launch-popup = pkgs.writeShellScriptBin "hakase-launch-popup" ''
|
hakase-launch-popup = pkgs.writeShellScriptBin "hakase-launch-popup" ''
|
||||||
if (($# == 0)); then
|
if (($# < 3)); then
|
||||||
echo "Usage: hakase-launch-popup [command]"
|
echo "Usage: hakase-launch-popup [width] [height] [command...]"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# --- ARGS & CONFIG ---
|
||||||
|
WIN_WIDTH="$1"
|
||||||
|
WIN_HEIGHT="$2"
|
||||||
|
shift 2
|
||||||
|
|
||||||
|
MARGIN=10
|
||||||
|
BAR_HEIGHT=40
|
||||||
|
# ---------------------
|
||||||
|
|
||||||
CMD_NAME=$(basename "$1")
|
CMD_NAME=$(basename "$1")
|
||||||
# Define a specific class for popups so Hyprland rules can catch them
|
TARGET_CLASS="org.hakase.popup.$CMD_NAME"
|
||||||
CLASS_NAME="org.hakase.popup.$CMD_NAME"
|
|
||||||
|
|
||||||
# Check if already running; if so, toggle/close it
|
# 1. SINGLETON LOGIC: Check for ANY existing hakase popup
|
||||||
EXISTING_ADDR=$(${pkgs.hyprland}/bin/hyprctl clients -j | ${pkgs.jq}/bin/jq -r --arg c "$CLASS_NAME" '.[] | select(.class == $c) | .address')
|
# We look for any client with a class starting with "org.hakase.popup."
|
||||||
|
EXISTING_JSON=$(${pkgs.hyprland}/bin/hyprctl clients -j | ${pkgs.jq}/bin/jq -r '.[] | select(.class | startswith("org.hakase.popup."))')
|
||||||
|
|
||||||
if [[ -n "$EXISTING_ADDR" ]]; then
|
if [[ -n "$EXISTING_JSON" ]]; then
|
||||||
${pkgs.hyprland}/bin/hyprctl dispatch closewindow "address:$EXISTING_ADDR"
|
OLD_ADDR=$(echo "$EXISTING_JSON" | ${pkgs.jq}/bin/jq -r '.address')
|
||||||
exit 0
|
OLD_CLASS=$(echo "$EXISTING_JSON" | ${pkgs.jq}/bin/jq -r '.class')
|
||||||
fi
|
|
||||||
|
|
||||||
# Launch the application
|
# Close the existing popup
|
||||||
# We use setsid to detach, but keep the PID to kill it later
|
${pkgs.hyprland}/bin/hyprctl dispatch closewindow "address:$OLD_ADDR"
|
||||||
xdg-terminal-exec --app-id="$CLASS_NAME" -e "$@" &
|
|
||||||
APP_PID=$!
|
|
||||||
|
|
||||||
# Wait for the window to appear and grab its address
|
# If the existing popup was the SAME one we are trying to launch, we are done (Toggle Off behavior)
|
||||||
TIMEOUT=0
|
if [[ "$OLD_CLASS" == "$TARGET_CLASS" ]]; then
|
||||||
WINDOW_ADDR=""
|
exit 0
|
||||||
while [[ -z "$WINDOW_ADDR" && $TIMEOUT -lt 20 ]]; do
|
|
||||||
sleep 0.1
|
|
||||||
WINDOW_ADDR=$(${pkgs.hyprland}/bin/hyprctl clients -j | ${pkgs.jq}/bin/jq -r --arg c "$CLASS_NAME" '.[] | select(.class == $c) | .address')
|
|
||||||
((TIMEOUT++))
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ -z "$WINDOW_ADDR" ]]; then
|
|
||||||
echo "Failed to find window for $CLASS_NAME"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Monitor Hyprland socket for focus changes
|
|
||||||
# We use socat to stream events. If activewindow changes to something else, kill the app.
|
|
||||||
${pkgs.socat}/bin/socat -U - UNIX-CONNECT:"$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock" | while read -r line; do
|
|
||||||
if [[ "$line" == "activewindow>>"* ]]; then
|
|
||||||
# Extract the new focused address
|
|
||||||
NEW_FOCUS="0x$(echo "$line" | cut -d '>' -f3 | cut -d ',' -f1)"
|
|
||||||
|
|
||||||
# If the new focus is NOT our popup window, kill the popup
|
|
||||||
if [[ "$WINDOW_ADDR" != "$NEW_FOCUS" ]]; then
|
|
||||||
kill "$APP_PID" 2>/dev/null
|
|
||||||
# Also force close in Hyprland to be sure
|
|
||||||
${pkgs.hyprland}/bin/hyprctl dispatch closewindow "address:$WINDOW_ADDR"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
# If it was a different popup, wait a tiny bit for Hyprland to process the close
|
||||||
|
# This prevents the new window from "merging" with the closing animation of the old one
|
||||||
|
sleep 0.15
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2. Calculate Geometry (Standard logic)
|
||||||
|
MONITOR_INFO=$(${pkgs.hyprland}/bin/hyprctl monitors -j | ${pkgs.jq}/bin/jq '.[] | select(.focused == true)')
|
||||||
|
MON_X=$(echo "$MONITOR_INFO" | ${pkgs.jq}/bin/jq '.x')
|
||||||
|
MON_Y=$(echo "$MONITOR_INFO" | ${pkgs.jq}/bin/jq '.y')
|
||||||
|
MON_WIDTH=$(echo "$MONITOR_INFO" | ${pkgs.jq}/bin/jq '.width')
|
||||||
|
|
||||||
|
TARGET_X=$((MON_X + MON_WIDTH - WIN_WIDTH - MARGIN))
|
||||||
|
TARGET_Y=$((MON_Y + BAR_HEIGHT + MARGIN))
|
||||||
|
|
||||||
|
# 3. Launch with Rules
|
||||||
|
RULE="[float;pin;size $WIN_WIDTH $WIN_HEIGHT;move $TARGET_X $TARGET_Y]"
|
||||||
|
${pkgs.hyprland}/bin/hyprctl dispatch exec "$RULE xdg-terminal-exec --app-id=$TARGET_CLASS -e $@"
|
||||||
|
|
||||||
|
# 4. Background Listener (Close on Blur)
|
||||||
|
(
|
||||||
|
TIMEOUT=0
|
||||||
|
WINDOW_ADDR=""
|
||||||
|
while [[ -z "$WINDOW_ADDR" && $TIMEOUT -lt 20 ]]; do
|
||||||
|
sleep 0.1
|
||||||
|
WINDOW_ADDR=$(${pkgs.hyprland}/bin/hyprctl clients -j | ${pkgs.jq}/bin/jq -r --arg c "$TARGET_CLASS" '.[] | select(.class == $c) | .address')
|
||||||
|
((TIMEOUT++))
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -n "$WINDOW_ADDR" ]]; then
|
||||||
|
${pkgs.socat}/bin/socat -U - UNIX-CONNECT:"$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock" | while read -r line; do
|
||||||
|
if [[ "$line" == "activewindow>>"* ]]; then
|
||||||
|
NEW_FOCUS="0x$(echo "$line" | cut -d '>' -f3 | cut -d ',' -f1)"
|
||||||
|
# If focus is lost to another window, close this popup
|
||||||
|
if [[ "$WINDOW_ADDR" != "$NEW_FOCUS" ]]; then
|
||||||
|
${pkgs.hyprland}/bin/hyprctl dispatch closewindow "address:$WINDOW_ADDR"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
) &
|
||||||
|
|
||||||
|
exit 0
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# 2. Specific Launchers using the Popup logic
|
# 1. WiFi (Impala) - Requires a larger view
|
||||||
hakase-popup-wifi = pkgs.writeShellScriptBin "hakase-popup-wifi" ''
|
hakase-popup-wifi = pkgs.writeShellScriptBin "hakase-popup-wifi" ''
|
||||||
exec hakase-launch-popup impala
|
exec hakase-launch-popup 800 500 impala
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
# 2. Bluetooth (Bluetui) - Fits your specific test size
|
||||||
hakase-popup-bluetooth = pkgs.writeShellScriptBin "hakase-popup-bluetooth" ''
|
hakase-popup-bluetooth = pkgs.writeShellScriptBin "hakase-popup-bluetooth" ''
|
||||||
exec hakase-launch-popup bluetui
|
exec hakase-launch-popup 600 500 bluetui
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
# 3. Volume (Wiremix) - Can be smaller
|
||||||
hakase-popup-volume = pkgs.writeShellScriptBin "hakase-popup-volume" ''
|
hakase-popup-volume = pkgs.writeShellScriptBin "hakase-popup-volume" ''
|
||||||
exec hakase-launch-popup wiremix
|
exec hakase-launch-popup 800 300 wiremix
|
||||||
'';
|
'';
|
||||||
in {
|
in {
|
||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
|
|||||||
Reference in New Issue
Block a user