218 lines
5.5 KiB
Plaintext
Executable File
218 lines
5.5 KiB
Plaintext
Executable File
#!/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] <org.my.desktop | /path/to/file>"
|
|
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 <thing.desktop>: open the desktop file (by name, not path)"
|
|
echo "--file </path/to/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': <false>}"
|
|
}
|
|
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"
|