add squeekboard, remove llm comments
This commit is contained in:
Executable
+187
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env bash
|
||||
# auto-rotate — rotate a wlroots output from iio-sensor-proxy orientation events.
|
||||
#
|
||||
# Unlike rot8 this does not read the accelerometer itself. iio-sensor-proxy owns
|
||||
# sensor selection (fuji has two accel_3d devices), applies its own hysteresis,
|
||||
# and reports `undefined` when the device is too flat to have a meaningful
|
||||
# orientation — so there is no dead zone in which we silently keep a stale state.
|
||||
#
|
||||
# SIGUSR1 toggle rotation lock (current transform is kept)
|
||||
# SIGUSR2 re-apply the last known orientation (e.g. after kanshi resets it)
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
OUTPUT="${AUTOROTATE_OUTPUT:-eDP-1}"
|
||||
HOOKS=()
|
||||
VERBOSE=0
|
||||
|
||||
usage() {
|
||||
cat <<-EOF
|
||||
usage: auto-rotate [-o OUTPUT] [-H HOOK]... [-v]
|
||||
|
||||
-o, --output OUTPUT output to rotate (default: ${OUTPUT})
|
||||
-H, --hook CMD run CMD after each rotation; may be repeated.
|
||||
\$ORIENTATION and \$PREV_ORIENTATION are exported.
|
||||
-v, --verbose log every sensor event, not just rotations
|
||||
EOF
|
||||
}
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-o | --output)
|
||||
OUTPUT="${2:?--output needs a value}"
|
||||
shift 2
|
||||
;;
|
||||
-H | --hook)
|
||||
HOOKS+=("${2:?--hook needs a value}")
|
||||
shift 2
|
||||
;;
|
||||
-v | --verbose)
|
||||
VERBOSE=1
|
||||
shift
|
||||
;;
|
||||
-h | --help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
printf 'auto-rotate: unknown argument: %s\n' "$1" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
for cmd in monitor-sensor wlr-randr; do
|
||||
command -v "$cmd" >/dev/null || {
|
||||
printf 'auto-rotate: %s not found in PATH\n' "$cmd" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
log() { printf '[auto-rotate] %s\n' "$*"; }
|
||||
vlog() { [ "$VERBOSE" = 1 ] && log "$@"; return 0; }
|
||||
|
||||
# iio-sensor-proxy orientation -> wlr-randr transform.
|
||||
#
|
||||
# NOTE: if the screen ends up 180 degrees off, swap the left-up and right-up
|
||||
# lines. This mapping is the common convention but it is not something the
|
||||
# sensor tells us, so it has to be confirmed by hand once.
|
||||
transform_for() {
|
||||
case "$1" in
|
||||
normal) printf 'normal' ;;
|
||||
left-up) printf '90' ;;
|
||||
bottom-up) printf '180' ;;
|
||||
right-up) printf '270' ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
current_transform() {
|
||||
wlr-randr 2>/dev/null |
|
||||
awk -v o="$OUTPUT" '
|
||||
$1 == o { found = 1; next }
|
||||
/^[^ \t]/ { found = 0 }
|
||||
found && $1 == "Transform:" { print $2; exit }
|
||||
'
|
||||
}
|
||||
|
||||
applied="$(current_transform)"
|
||||
[ -n "$applied" ] || {
|
||||
printf 'auto-rotate: output %s not found\n' "$OUTPUT" >&2
|
||||
exit 1
|
||||
}
|
||||
log "output ${OUTPUT}, current transform ${applied}"
|
||||
|
||||
orientation="" # last non-undefined orientation from the sensor
|
||||
prev_orientation="" # the one before that, exported to hooks
|
||||
locked=0
|
||||
|
||||
toggle_lock() {
|
||||
locked=$((1 - locked))
|
||||
[ "$locked" = 1 ] && log "rotation locked at ${applied}" || log "rotation unlocked"
|
||||
}
|
||||
|
||||
apply() {
|
||||
local target
|
||||
target="$(transform_for "$orientation")" || return 0
|
||||
[ "$target" = "$applied" ] && return 0
|
||||
|
||||
if ! wlr-randr --output "$OUTPUT" --transform "$target"; then
|
||||
# Do not advance `applied` — a failed rotation must not desync our idea
|
||||
# of the output state from reality. This was rot8's other failure mode.
|
||||
log "wlr-randr failed, keeping transform as ${applied}"
|
||||
return 0
|
||||
fi
|
||||
log "${applied} -> ${target} (${orientation})"
|
||||
applied="$target"
|
||||
|
||||
local hook
|
||||
for hook in ${HOOKS+"${HOOKS[@]}"}; do
|
||||
ORIENTATION="$orientation" PREV_ORIENTATION="$prev_orientation" \
|
||||
bash -c "$hook" || log "hook failed: ${hook}"
|
||||
done
|
||||
}
|
||||
|
||||
reapply() {
|
||||
applied="$(current_transform)"
|
||||
log "re-syncing, output is at ${applied}"
|
||||
[ "$locked" = 0 ] && [ -n "$orientation" ] && apply
|
||||
return 0
|
||||
}
|
||||
|
||||
trap toggle_lock USR1
|
||||
trap reapply USR2
|
||||
|
||||
exec 3< <(stdbuf -oL monitor-sensor 2>&1)
|
||||
monitor_pid=$!
|
||||
trap 'kill "$monitor_pid" 2>/dev/null; exit 0' INT TERM EXIT
|
||||
|
||||
while :; do
|
||||
# A signal interrupts read; that is not an error, so retry rather than exit.
|
||||
IFS= read -r line <&3 || {
|
||||
kill -0 "$monitor_pid" 2>/dev/null && continue
|
||||
break
|
||||
}
|
||||
|
||||
case "$line" in
|
||||
*"Accelerometer orientation changed: "*)
|
||||
new="${line##*: }"
|
||||
;;
|
||||
*"Has accelerometer (orientation: "*)
|
||||
# The initial state only ever arrives on this banner line; a
|
||||
# "changed" line is not emitted until the orientation moves.
|
||||
new="${line#*orientation: }"
|
||||
new="${new%%,*}"
|
||||
;;
|
||||
*"iio-sensor-proxy appeared"*)
|
||||
# The proxy restarted; our cached transform may be stale.
|
||||
reapply
|
||||
continue
|
||||
;;
|
||||
*"Compass heading changed"*)
|
||||
# ~1 Hz of noise we have no use for; drop it even when verbose.
|
||||
continue
|
||||
;;
|
||||
*)
|
||||
vlog "$line"
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
vlog "sensor says ${new}"
|
||||
|
||||
# `undefined` means the device is lying too flat to tell. Hold position.
|
||||
[ "$new" = undefined ] && continue
|
||||
[ "$new" = "$orientation" ] && continue
|
||||
|
||||
prev_orientation="$orientation"
|
||||
orientation="$new"
|
||||
|
||||
[ "$locked" = 1 ] && {
|
||||
vlog "locked, ignoring ${orientation}"
|
||||
continue
|
||||
}
|
||||
apply
|
||||
done
|
||||
|
||||
log "monitor-sensor exited"
|
||||
Reference in New Issue
Block a user