MAX_TITLE_LENGTH=600 get_windows_with_workspace() { swaymsg -t get_tree | jq -r --arg max_len "$MAX_TITLE_LENGTH" ' def get_workspace_name(node): if node.type == "workspace" then node.name elif node.parent then get_workspace_name(node.parent) else "Unknown" end; def get_windows(workspace_name): if .type == "con" and .pid != null and (.name // "") != "" then { id: .id, name: .name, app_id: (.app_id // .window_properties.class // "Unknown"), workspace: workspace_name, focused: .focused } else empty end, (.nodes[]? | get_windows(workspace_name)), (.floating_nodes[]? | get_windows(workspace_name)); def get_workspaces: if .type == "workspace" then . as $ws | .name as $ws_name | get_windows($ws_name) else empty end, (.nodes[]? | get_workspaces); get_workspaces | "\(.id)|\(.app_id)|\(.name)|\(.workspace)|\(.focused)" ' } window_list=$(get_windows_with_workspace) formatted_list=$(echo "$window_list" | while IFS='|' read -r id app_id name workspace focused; do if [ ${#name} -gt $MAX_TITLE_LENGTH ]; then truncated_name="${name:0:$((MAX_TITLE_LENGTH-3))}..." else truncated_name="$name" fi if [ "$focused" = "true" ]; then indicator="> " else indicator=" " fi printf "[%s/%s]%s %s: %s\n" "$workspace" "$id" "$indicator" "$app_id" "$truncated_name" done) selection=$(echo "$formatted_list" | bemenu --prompt "/" --index "$(echo "$formatted_list" | awk '/]>/ {print NR-1 ":" $0}')" ) [ -z "$selection" ] && exit 0 window_id=$(echo "$selection" | sed 's/.*\/\([^]]*\)].*/\1/') if [ -n "$window_id" ]; then swaymsg "[con_id=\"$window_id\"] focus" else echo "Failed to extract window ID." exit 1 fi