diff --git a/env/.config/hypr/keybinds.conf b/env/.config/hypr/keybinds.conf index 46c88b4..762561a 100644 --- a/env/.config/hypr/keybinds.conf +++ b/env/.config/hypr/keybinds.conf @@ -35,16 +35,16 @@ bindd = $mainMod, SPACE, Application launcher, exec, bindd = $mainMod, RETURN, New terminal, exec, $terminal bindd = $mainMod SHIFT, RETURN, New floating terminal, exec, $terminal --class=com.ghostty.float bindd = $mainMod, TAB, Focus previous workspace, workspace, previous -bindd = $mainMod, A, [A]i - launch / focus, exec, $pwa --focus "https://chatgpt.com" +bindd = $mainMod, A, [A]i - launch / focus, exec, $pwa --or-focus "https://chatgpt.com" bindd = $mainMod SHIFT, A, [A]i - new window, exec, $pwa "https://chatgpt.com" bindd = $mainMod, B, New [b]rowser, exec, $browser bindd = $mainMod SHIFT, B, New private [b]rowser, exec, $browser --private-window -bindd = $mainMod, C, [C]alendar, exec, $pwa --focus "https://www.icloud.com/calendar" +bindd = $mainMod, C, [C]alendar, exec, $pwa --or-focus "https://www.icloud.com/calendar" bindd = $mainMod SHIFT, C, [C]onfig folder in tmux session, exec, $terminal -e $tmuxSessionator ~/.config bindd = $mainMod, D, [D]ispatch app - special workspace, exec, $pwa --special dispatch $housecallPro bindd = $mainMod SHIFT, D, [D]ispatch app - new window, exec, $pwa $housecallPro -bindd = $mainMod, E, [E]mail - personal, exec, $pwa --focus "https://mail.proton.me" -bindd = $mainMod SHIFT, E, [E]mail - work, exec, $scripts/launch-or --focus thunderbird uwsm app -- thunderbird +bindd = $mainMod, E, [E]mail - personal, exec, $pwa --or-focus "https://mail.proton.me" +bindd = $mainMod SHIFT, E, [E]mail - work, exec, $scripts/launch --or-focus thunderbird uwsm app -- thunderbird bindd = $mainMod, F, [F]ile manager - terminal, exec, $fileManager bindd = $mainMod SHIFT, F, [F]ile manager - application, exec, $fileBrowser bindd = $mainMod, G, [G]itea, exec, $pwa "https://git.housh.dev" @@ -61,10 +61,10 @@ bindd = $mainMod, P, [P]assword manager, exec, bindd = $mainMod SHIFT, P, Toggle [p]seudo window mode, pseudo, # dwindle bindd = $mainMod SHIFT, R, [R]estart menu bar, exec, $scripts/waybar-restart bindd = $mainMod, S, Toggle [s]pecial workspace, togglespecialworkspace, magic # use $windowMod S to send window to the special workspace -bindd = $mainMod, Y, [Y]ouTube, exec, $pwa --focus "https://youtube.com" +bindd = $mainMod, Y, [Y]ouTube, exec, $pwa --or-focus "https://youtube.com" bindd = $mainMod, U, [U]nifi, exec, $pwa "https://unifi.ui.com" bindd = $mainMod SHIFT, U, [U]ninstall desktop app, exec, $uninstallDesktop -bindd = $mainMod, V, Clipboard history, exec, $scripts/launch-or --close $clipboardHistory +bindd = $mainMod, V, Clipboard history, exec, $scripts/launch --or-close $clipboardHistory bindd = $mainMod, W, Close current window, killactive, bindd = $mainMod SHIFT, W, Close all windows in active workspace, exec, $scripts/close-windows --active-workspace diff --git a/env/.local/scripts/launch b/env/.local/scripts/launch new file mode 100755 index 0000000..7f5d9c6 --- /dev/null +++ b/env/.local/scripts/launch @@ -0,0 +1,125 @@ +#!/usr/bin/env bash + +usage() { + cat <: Launch or toggle a special workspace. + -h | --help: Show this help page. + +NOTES: + + Passing both a '--close' and '--focus' flag will result in an error if a window is found matching +the pattern. + + If the special option is passed then we will not attempt to close a window. If the script is +invoked with the special option set, we check if there is a window matching the pattern, if there +is and the currently active window is on the same workspace passed in to the special option, then +we toggle the workspace closed. This allows the same keybind to be used to launch an application +in a special workspace as well as toggle the workspace closed. + +EOF +} + +action="focuswindow" +close_flag="0" +focus_flag="0" +launch_cmd=() +pattern="" +special_flag="0" +special="" + +while [[ $# -gt 0 ]]; do + if [[ $1 == "-c" ]] || [[ $1 == "--or-close" ]]; then + close_flag="1" + action="closewindow" + elif [[ $1 == "-f" ]] || [[ $1 == "--or-focus" ]]; then + focus_flag="1" + action="focuswindow" + elif [[ $1 == "-s" ]] || [[ $1 == "--special" ]]; then + shift + special_flag="1" + special=$1 + elif [[ $1 == "-h" ]] || [[ $1 == "--help" ]]; then + usage && exit 0 + elif [[ -z $pattern ]]; then + pattern=$1 + else + launch_cmd+=("$1") + fi + shift +done + +toggle_special() { + if [[ -z $special ]]; then + echo "[ERROR]: No name supplied for special workspace." + exit 1 + fi + hyprctl dispatch togglespecialworkspace $special +} + +################################################################################ +# MAIN +################################################################################ + +if [[ -z $pattern ]]; then + echo "[ERROR]: Must supply a pattern to match the window class." + usage && exit 1 +elif [[ -z $launch_cmd ]]; then + echo "[ERROR]: Must supply a launch command to match the window class." + usage && exit 1 +fi + +# Get first window matching the pattern. +address=$(hyprctl clients -j | jq -r ".[] | select(.class | contains(\"$pattern\")) | .address") + +echo "Pattern: $pattern" +echo "Address: $address" + +# Check if we found a window address. +if [[ -n $address ]]; then + + # Get the workspace name of the active window. + active_window_workspace=$(hyprctl activewindow -j | jq -r '.workspace.name') + echo "Active window workspace: $active_window_workspace" + + # Check if we have special flag and active window is on the special workspace. If so + # we just toggle the special workspace. This keeps "special" apps alive, but closes and / opens + # the special workspace when invoked. + if [[ $special_flag == "1" ]] && [[ $active_window_workspace =~ $special ]]; then + toggle_special && exit 0 + fi + + # Check if both close and focus flags were passed, so we don't do the + # wrong thing. + if [[ $focus_flag == "1" ]] && [[ $close_flag == "1" ]]; then + echo "[ERROR]: Both focus and close flag were passed." + exit 1 + fi + + # We didn't have the special flag, so dispatch the command (focus or close). + echo "Found window, dispatching action: $action" + hyprctl dispatch $action "address:$address" +else + # We did not find an address matching the pattern. + # + # Toggle a special workspace, if applicable before launching. + if [[ $special_flag == "1" ]]; then + toggle_special + fi + echo "Launching..." + echo "'${launch_cmd[@]}'" + eval exec ${launch_cmd[@]} +fi diff --git a/env/.local/scripts/launch-or b/env/.local/scripts/launch-or deleted file mode 100755 index 4079fdb..0000000 --- a/env/.local/scripts/launch-or +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env bash - -usage() { - cat <: Launch in the special workspace name, or toggle the special workspace. @@ -21,7 +22,13 @@ OPTIONS: NOTES: -Any extra arguments after the url get passed directly to the browser invocation. +Any extra arguments after '--' get passed directly to the browser invocation. + + $ launch-webapp https://example.com -- --some-random-flag-for-browser=1 + +Any options passed in prior to the '--' get sent to the 'launch-or' script, so you can pass +options that are not specifically shown here, but the ones shown would be the most commonly +used, so they are documented here. Using the '--special' flag is useful for apps that you want to have a "summoning" like behavior. Upon first launch the application will be opened and the special workspace will be shown. @@ -33,12 +40,9 @@ EOF } browser="chromium.desktop" -special="" -special_flag="0" -focus_flag="0" -help_flag="0" url="" -args=() +launch_args=() +app_args="" SCRIPTS="${SCRIPTS}" if [[ -z $SCRIPTS ]]; then @@ -49,30 +53,22 @@ fi while [[ $# -gt 0 ]]; do if [[ $1 =~ ^--special ]] || [[ $1 =~ ^-s ]]; then - shift - special_flag="1" - special=$1 - elif [[ $1 =~ ^--focus ]] || [[ $1 =~ ^-f ]]; then - focus_flag="1" + launch_args+=("$1") + launch_args+=("$2") + shift # Second shift get's handled below elif [[ $1 =~ ^--help ]] || [[ $1 =~ ^-h ]]; then - help_flag="1" - elif [[ -z $url ]]; then + usage && exit 0 + elif [[ -z $url ]] && [[ ! $1 =~ ^- ]]; then url=$1 + elif [[ $1 == "--" ]]; then + shift + break else - args+=($1) + launch_args+=("$1") fi shift done -# Early out if help flag was supplied. -if [[ $help_flag == "1" ]]; then - usage && exit 0 -fi - -launch() { - exec setsid uwsm app -- $(sed -n 's/^Exec=\([^ ]*\).*/\1/p' {~/.local,~/.nix-profile,/usr}/share/applications/$browser 2>/dev/null | head -1) --app="$1" "$2" -} - # Strips url down to just the domain, so that we can match window classes. pattern() { pattern=${url/#https:\/\//} @@ -81,68 +77,20 @@ pattern() { echo $pattern } -getWindowProp() { - echo $(hyprctl clients -j | jq -r ".[] | select((.class | contains(\"$(pattern)\"))) | .$1" | head -n 1) -} - -log() { - echo "[$($SCRIPTS/isosec)] - $1" >>/tmp/launch-webapp.log -} - -fail() { - echo -e "\n\e[31m[Error]: $1\e[0m" - log "[Error]: $1" -} - -handleSpecial() { - local window_addr=$(getWindowProp address) - local window_workspace=$(getWindowProp workspace.id) - local active_workspace=$(hyprctl activeworkspace -j | jq -r ".id") - local special_workspace_id=$(hyprctl workspaces -j | jq -r ".[] | select(.name | contains(\"$special\")) | .id") - - log "Window: address: $window_addr workspace: $window_workspace" - log "Special workspace: $special id: $special_workspace_id" - log "Active workspace: $active_workspace" - - # Check if we don't have a window address, or if the window is not on the expected special workspace. - if [[ -z $window_addr ]] || ([[ -n $window_workspace ]] && [[ $window_workspace != $special_workspace_id ]]); then - log "No window, launching..." - hyprctl dispatch togglespecialworkspace $special - launch $url $args - else - log "We have a window, toggling special workspace" - hyprctl dispatch togglespecialworkspace $special - fi -} - ################################################## # MAIN ################################################## if [[ -z $url ]]; then - fail "Must supply a url." && usage && exit 1 + echo "[ERROR]: Must supply a url." && usage && exit 1 fi -if [[ $special_flag == "1" ]]; then - log "Handling special workspace..." - if [[ -z $special ]]; then - fail "Must supply special workspace name." && exit 1 - fi - handleSpecial && exit 0 -fi +# Any left over args after "--" +app_args="$@" -window_addr="" +echo "URL: $url" +echo "Launch args: ${launch_args[@]}" +echo "App args: ${app_args}" -if [[ $focus_flag == "1" ]]; then - log "Received focus flag, checking for window address." - window_addr=$(getWindowProp address) - log "Window address: $window_addr" -fi - -if [[ -n $window_addr ]]; then - log "No window address launching..." - hyprctl dispatch focuswindow "address:$window_addr" - exit 0 -fi - -launch $url $args +$SCRIPTS/launch "${launch_args[@]}" "$(pattern)" \ + setsid uwsm app -- $(sed -n 's/^Exec=\([^ ]*\).*/\1/p' {~/.local,~/.nix-profile,/usr}/share/applications/$browser 2>/dev/null | head -1) --app="$url" "$app_args"