diff options
Diffstat (limited to 'raveos-theme/hyprland/theme-data/hypr/scripts')
| -rwxr-xr-x | raveos-theme/hyprland/theme-data/hypr/scripts/alt-tab.sh | 273 | ||||
| -rwxr-xr-x | raveos-theme/hyprland/theme-data/hypr/scripts/raveos-monitor-setup.sh | 100 |
2 files changed, 373 insertions, 0 deletions
diff --git a/raveos-theme/hyprland/theme-data/hypr/scripts/alt-tab.sh b/raveos-theme/hyprland/theme-data/hypr/scripts/alt-tab.sh new file mode 100755 index 0000000..0a40f9d --- /dev/null +++ b/raveos-theme/hyprland/theme-data/hypr/scripts/alt-tab.sh @@ -0,0 +1,273 @@ +#!/bin/bash + +STATE_DIR="/tmp/hypr-alt-tab" +STATE_FILE="$STATE_DIR/state" +TIME_FILE="$STATE_DIR/last_press" +CURRENT_INDEX_FILE="$STATE_DIR/current_index" +WINDOW_LIST_FILE="$STATE_DIR/window_list" + +# Cooldown in seconds (time within which presses count as "continuous") +COOLDOWN=0.8 + +# Create state directory if it doesn't exist +mkdir -p "$STATE_DIR" + +# Parse arguments +same_type=false +reverse=false +visible_only=false + +for arg in "$@"; do + case $arg in + --same) same_type=true ;; + --reverse) reverse=true ;; + --visible) visible_only=true ;; + esac +done + +# Function to get window class +get_window_class() { + local window="$1" + hyprctl clients -j | jq -r --arg addr "$window" '.[] | select(.address == $addr) | .class' +} + +# Function to get window title +get_window_title() { + local window="$1" + hyprctl clients -j | jq -r --arg addr "$window" '.[] | select(.address == $addr) | .title' +} + +# Function to get window workspace ID +get_window_workspace() { + local window="$1" + hyprctl clients -j | jq -r --arg addr "$window" '.[] | select(.address == $addr) | .workspace.id' +} + +# Function to get active workspaces (visible on monitors) +get_active_workspaces() { + hyprctl monitors -j | jq -r '.[].activeWorkspace.id' +} + +# Function to get all windows sorted by focus history (most recent first) +get_windows_by_focus() { + hyprctl clients -j | jq -r 'sort_by(-.focusHistoryID) | .[].address' +} + +# Function to get visible windows (on active workspaces) +get_visible_windows() { + # Get all active workspace IDs + mapfile -t active_workspaces < <(get_active_workspaces) + + if [[ ${#active_workspaces[@]} -eq 0 ]]; then + return + fi + + # Convert active workspaces to JSON array for jq query + local workspaces_json="[" + for ws in "${active_workspaces[@]}"; do + workspaces_json+="$ws," + done + workspaces_json="${workspaces_json%,}]" + + # Get windows in active workspaces, sorted by focus history + hyprctl clients -j | jq -r --argjson workspaces "$workspaces_json" ' + [.[] | select(.workspace.id as $ws | $workspaces | index($ws))] + | sort_by(-.focusHistoryID) + | .[].address + ' +} + +# Function to get windows filtered by type (same class or title pattern) +get_same_type_windows() { + local current_window="$1" + local current_class=$(get_window_class "$current_window") + local current_title=$(get_window_title "$current_window") + + # Get all windows with same class + hyprctl clients -j | jq -r --arg class "$current_class" \ + '.[] | select(.class == $class) | .address' +} + +# Function to get currently focused window +get_focused_window() { + hyprctl activewindow -j | jq -r '.address' +} + +# Function to check if window exists +window_exists() { + local window="$1" + [[ -n "$window" ]] && hyprctl clients -j | jq -r '.[].address' | grep -q "^${window}$" +} + +# Function to validate and refresh window list +validate_window_list() { + local windows=("$@") + local valid_windows=() + + for window in "${windows[@]}"; do + if window_exists "$window"; then + valid_windows+=("$window") + fi + done + + printf '%s\n' "${valid_windows[@]}" +} + +# Get currently focused window +current_focused=$(get_focused_window) + +# Get appropriate window list based on mode +if [[ "$visible_only" == "true" ]]; then + # Get only windows in active workspaces (visible on monitors) + echo "Switching between visible windows only" >&2 + mapfile -t windows < <(get_visible_windows) + + # If no visible windows, fall back to all windows + if [[ ${#windows[@]} -eq 0 ]]; then + echo "No visible windows found, falling back to all windows" >&2 + mapfile -t windows < <(get_windows_by_focus) + fi + + # Apply same-type filter if requested + if [[ "$same_type" == "true" ]] && [[ -n "$current_focused" ]]; then + # Get windows of the same type as current (from visible windows) + mapfile -t same_type_windows < <(get_same_type_windows "$current_focused") + + # Filter visible windows to only include same-type windows + local filtered_windows=() + for visible_window in "${windows[@]}"; do + for same_window in "${same_type_windows[@]}"; do + if [[ "$visible_window" == "$same_window" ]]; then + filtered_windows+=("$visible_window") + break + fi + done + done + + # If filtered list has windows, use it + if [[ ${#filtered_windows[@]} -gt 0 ]]; then + windows=("${filtered_windows[@]}") + else + echo "No visible windows of same type, using all visible windows" >&2 + fi + fi +elif [[ "$same_type" == "true" ]] && [[ -n "$current_focused" ]]; then + # Get windows of the same type as current (from all windows) + mapfile -t windows < <(get_same_type_windows "$current_focused") + + # If no same-type windows or only current window, fall back to all windows + if [[ ${#windows[@]} -le 1 ]]; then + echo "No other windows of same type found, switching to all windows" >&2 + mapfile -t windows < <(get_windows_by_focus) + fi +else + # Get all windows + mapfile -t windows < <(get_windows_by_focus) +fi + +# Validate windows still exist +mapfile -t windows < <(validate_window_list "${windows[@]}") + +# Exit if no windows or only one window +if [[ ${#windows[@]} -le 1 ]]; then + echo "Not enough windows to switch" >&2 + exit 0 +fi + +# Get current time +current_time=$(date +%s.%N) + +# Read last press time +last_press=0 +[[ -f "$TIME_FILE" ]] && last_press=$(<"$TIME_FILE") + +# Calculate time difference +time_diff=$(echo "$current_time - $last_press" | bc -l 2>/dev/null || echo "1") + +# Check if we're continuing the Alt+Tab session +continuing_session=false +if (( $(echo "$time_diff <= $COOLDOWN" | bc -l 2>/dev/null || echo "0") )); then + continuing_session=true +fi + +# Find current window index in the list +current_index=-1 +for i in "${!windows[@]}"; do + if [[ "${windows[$i]}" == "$current_focused" ]]; then + current_index=$i + break + fi +done + +# If current window not in filtered list, start from beginning +if [[ $current_index -eq -1 ]]; then + current_index=0 +fi + +# Calculate target index +if [[ "$continuing_session" == "true" ]] && [[ -f "$CURRENT_INDEX_FILE" ]] && [[ -f "$WINDOW_LIST_FILE" ]]; then + # Read saved state + saved_index=$(<"$CURRENT_INDEX_FILE") + mapfile -t saved_windows < "$WINDOW_LIST_FILE" + + # Check if saved windows match current windows + same_list=true + if [[ ${#windows[@]} -ne ${#saved_windows[@]} ]]; then + same_list=false + else + for i in "${!windows[@]}"; do + if [[ "${windows[$i]}" != "${saved_windows[$i]}" ]]; then + same_list=false + break + fi + done + fi + + if [[ "$same_list" == "true" ]]; then + if [[ "$reverse" == "true" ]]; then + target_index=$(( (saved_index - 1 + ${#windows[@]}) % ${#windows[@]} )) + else + target_index=$(( (saved_index + 1) % ${#windows[@]} )) + fi + else + # List changed, recalculate from current + if [[ "$reverse" == "true" ]]; then + target_index=$(( (current_index - 1 + ${#windows[@]}) % ${#windows[@]} )) + else + target_index=$(( (current_index + 1) % ${#windows[@]} )) + fi + fi +else + # Start new session - move from current window + if [[ "$reverse" == "true" ]]; then + target_index=$(( (current_index - 1 + ${#windows[@]}) % ${#windows[@]} )) + else + target_index=$(( (current_index + 1) % ${#windows[@]} )) + fi +fi + +# Save state +echo "$current_time" > "$TIME_FILE" +echo "$target_index" > "$CURRENT_INDEX_FILE" +printf '%s\n' "${windows[@]}" > "$WINDOW_LIST_FILE" + +# Focus the target window +target_window="${windows[$target_index]}" +if window_exists "$target_window"; then + echo "Switching to window: $target_window (Class: $(get_window_class "$target_window"), Workspace: $(get_window_workspace "$target_window"))" >&2 + hyprctl dispatch focuswindow "address:$target_window" + hyprctl dispatch bringactivetotop +fi + +# Visual feedback: dim inactive windows temporarily +hyprctl keyword decoration:dim_inactive true 2>/dev/null + +# Clear any existing reset timer +[[ -f "$STATE_DIR/dim_timer" ]] && kill "$(<"$STATE_DIR/dim_timer")" 2>/dev/null || true + +# Start timer to reset dimming +( + sleep 1.2 + hyprctl keyword decoration:dim_inactive false 2>/dev/null +) & +echo $! > "$STATE_DIR/dim_timer" diff --git a/raveos-theme/hyprland/theme-data/hypr/scripts/raveos-monitor-setup.sh b/raveos-theme/hyprland/theme-data/hypr/scripts/raveos-monitor-setup.sh new file mode 100755 index 0000000..2790ee4 --- /dev/null +++ b/raveos-theme/hyprland/theme-data/hypr/scripts/raveos-monitor-setup.sh @@ -0,0 +1,100 @@ +#!/bin/bash +# raveos-monitor-setup - Auto-detect monitors and generate Hyprland config +# Sets each monitor to max resolution at 60Hz +# +# Usage: raveos-monitor-setup.sh [--hypr-dir PATH] +# Default hypr dir: ~/.config/hypr + +HYPR_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr" + +# Parse arguments +while [[ $# -gt 0 ]]; do + case "$1" in + --hypr-dir) HYPR_DIR="$2"; shift 2 ;; + *) shift ;; + esac +done + +MONITORS_CONF="$HYPR_DIR/monitors.conf" +WORKSPACES_CONF="$HYPR_DIR/workspaces.conf" + +# Find connected monitors via DRM sysfs +declare -a MON_NAMES +declare -a MON_RESOLUTIONS +declare -a MON_WIDTHS + +for card_output in /sys/class/drm/card*-*; do + [[ ! -d "$card_output" ]] && continue + + status=$(cat "$card_output/status" 2>/dev/null) + [[ "$status" != "connected" ]] && continue + + # Get output name: card0-DP-1 → DP-1, card1-HDMI-A-1 → HDMI-A-1 + raw_name=$(basename "$card_output") + name="${raw_name#card*-}" + + # Get available modes (first line = highest resolution) + modes_file="$card_output/modes" + if [[ -f "$modes_file" ]]; then + max_mode=$(head -1 "$modes_file") + if [[ -n "$max_mode" ]]; then + # Extract width from resolution (e.g., 2560x1440 → 2560) + width="${max_mode%%x*}" + MON_NAMES+=("$name") + MON_RESOLUTIONS+=("$max_mode") + MON_WIDTHS+=("$width") + fi + fi +done + +# If no monitors found, use fallback +if [[ ${#MON_NAMES[@]} -eq 0 ]]; then + cat > "$MONITORS_CONF" << 'EOF' +# Auto-generated by raveos-monitor-setup +# No monitors detected - using fallback +monitor=,preferred,auto,1 +EOF + cat > "$WORKSPACES_CONF" << 'EOF' +# Auto-generated by raveos-monitor-setup +# No monitors detected +EOF + echo "No monitors detected, using fallback config" + exit 0 +fi + +# Generate monitors.conf +cat > "$MONITORS_CONF" << 'EOF' +# Auto-generated by raveos-monitor-setup +# Run raveos-monitor-setup.sh to reconfigure monitors +EOF + +pos_x=0 +for ((i=0; i<${#MON_NAMES[@]}; i++)); do + echo "monitor=${MON_NAMES[$i]}, ${MON_RESOLUTIONS[$i]}@60, ${pos_x}x0, 1" >> "$MONITORS_CONF" + pos_x=$((pos_x + MON_WIDTHS[i])) +done + +# Generate workspaces.conf - distribute 10 workspaces across monitors +cat > "$WORKSPACES_CONF" << 'EOF' +# Auto-generated by raveos-monitor-setup +EOF + +num_monitors=${#MON_NAMES[@]} +ws_per_mon=$((10 / num_monitors)) +remaining=$((10 % num_monitors)) + +ws=1 +for ((i=0; i<num_monitors; i++)); do + count=$ws_per_mon + [[ $i -lt $remaining ]] && ((count++)) + + for ((j=0; j<count; j++)); do + echo "workspace=$ws, monitor:${MON_NAMES[$i]}, persistent:1" >> "$WORKSPACES_CONF" + ((ws++)) + done +done + +echo "Monitor setup complete: ${#MON_NAMES[@]} monitor(s) configured" +for ((i=0; i<${#MON_NAMES[@]}; i++)); do + echo " ${MON_NAMES[$i]}: ${MON_RESOLUTIONS[$i]}@60" +done |