#!/usr/bin/env nix-shell #!nix-shell -i bash -p bash -p glib -p jq -p procps -p sway -p util-linux -p xdg-utils set -e usage() { echo "usage: sane-open [options] " echo "given some resource, ask the xdg-desktop-portal service to open it" echo "this could be either the name of an application, or a URI identifying a file" echo echo "options:" echo "--auto-keyboard: toggle the virtual keyboard state to whatever's preferred by the app" echo "--application : open the desktop file (by name, not path)" echo "--file : open the file using the default mime handler" exit $1 } log() { if [ -n "$SANE_OPEN_DEBUG" ]; then printf 'sane-open: %s\n' "$1" >&2 fi } configureKeyboardFor_application() { case "$1" in Alacritty.desktop) setKeyboard show ;; app.drey.Dialect.desktop) setKeyboard showIfRoom ;; com.github.hugolabe.Wike.desktop) setKeyboard showIfRoom ;; # io.github.lainsce.Notejot.desktop) # setKeyboard showIfRoom # ;; org.gnome.Epiphany.desktop) setKeyboard showIfRoom ;; rofi.desktop) setKeyboard showIfRoom ;; rofi-applications.desktop) setKeyboard showIfRoom ;; rofi-filebrowser.desktop) setKeyboard showIfRoom ;; rofi-snippets.desktop) setKeyboard showIfRoom ;; sane-screenshot.desktop) # leave unchanged ;; xdg-terminal-exec.desktop) setKeyboard show ;; *) setKeyboard hide ;; esac } configureKeyboardFor_file() { local mime=$(xdg-mime query filetype "$1") local application=$(xdg-mime query default "$mime") configureKeyboardFor_application "$application" } open_application() { log "open_application: '$1'" gdbus call --session --timeout 10 \ --dest org.freedesktop.portal.Desktop \ --object-path /org/freedesktop/portal/desktop \ --method org.freedesktop.portal.DynamicLauncher.Launch \ "$1" {} } open_file() { # open the file, and then pass the fd to dbus log "open_file: '$1'" exec 3< "$1" gdbus call --session --timeout 10 \ --dest org.freedesktop.portal.Desktop \ --object-path /org/freedesktop/portal/desktop \ --method org.freedesktop.portal.OpenURI.OpenFile \ '' 3 "{'ask': }" } open_desktopFile() { log "open_desktopFile: '$1'" # open_application (i.e. the DynamicLauncher portal) only understands applications by their # .desktop filename (relative to ~/.local/share/applications) -- not by their full path. # therefore, see if this .desktop file is equivalent to anything in ~/.local/share/applications. local path="$1" if [[ "${path:0:1}" != "/" ]]; then path="$PWD/$path" fi if [[ "$path" == $HOME/.local/share/applications/*.desktop ]]; then open_application "$(basename "$path")" return fi # the given path doesn't exist in ~/.local/share/applications: check if it's a symlink which # derefs to an application local target="$(readlink "$path")" if [ -z "$target" ]; then log "open_desktopFile: '$path' does not deref to anything in ~/.local/share/applications: falling back to heuristics" # assume that the deref'd name matches the application name. # there's nothing *guaranteeing* this, but i have yet to see it fail. open_application "$(basename "$path")" return fi if [[ "${target:0:1}" != "/" ]]; then target="$(dirname "$path")/$target" fi open_desktopFile "$target" } isLandscape() { # success if all outputs are landscape swaymsg -t get_outputs --raw \ | jq --exit-status '. | all(.transform == "90" or .transform == "270")' \ > /dev/null } _keyboardPid= setKeyboard() { if [ -z "$KEYBOARD" ]; then log "KEYBOARD is not set" return fi if [ -z "$_keyboardPid" ]; then _keyboardPid=$(pidof "$KEYBOARD") if [ -z "$_keyboardPid" ]; then log "KEYBOARD ($KEYBOARD) instance is not found" return fi fi _setKeyboard "$1" } _setKeyboard() { case "$1" in "show") log "show keyboard $_keyboardPid" # `env` so that we get the util-linux `kill` binary instead of bash's builtin env kill -s USR2 "$_keyboardPid" ;; "showIfRoom") isLandscape && _setKeyboard "hide" || _setKeyboard "show" ;; "hide") log "hide keyboard $_keyboardPid" env kill -s USR1 "$_keyboardPid" ;; esac } ## ARGUMENT PARSING autoKeyboard= resource= resourceType= while [ $# -gt 0 ]; do arg="$1" shift case "$arg" in "--auto-keyboard") autoKeyboard=1 ;; "--help") usage 0 ;; "--application") resourceType="application" ;; "--desktop-file") resourceType="desktopFile" ;; "--file") resourceType="file" ;; *) if [ $# -ne 0 ]; then usage 1 fi resource="$arg" ;; esac done if [ -z "$resourceType" ]; then if [ -e "$HOME/.local/share/applications/$resource" ]; then log "detected resourceType=application" resourceType=application elif [ -e "$resource" ]; then log "detected resourceType=file" resourceType=file elif [[ "$resource" == *.desktop ]]; then log "detected resourceType=application (warning: '$resource' is not visible on disk)" resourceType=application else log "detected resourceType=file (warning: '$resource' is not visible on disk)" resourceType=file fi fi ## TOPLEVEL LOGIC if [ -n "$autoKeyboard" ]; then # do in parallel to avoid delaying app launch configureKeyboardFor_"$resourceType" "$resource" & fi open_"$resourceType" "$resource"