212 lines
5.8 KiB
Bash
212 lines
5.8 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# middleclick-autoscroll: middle-click autoscroll for Chromium-based
|
|
# applications on Linux
|
|
#
|
|
# Blink has had Windows-style autoscroll for years, behind a runtime flag that
|
|
# is not turned on for Linux because middle click is taken by primary-selection
|
|
# paste there. Turning it on is a matter of one command line argument. The
|
|
# work is finding every application that needs it, putting the argument
|
|
# somewhere it survives an update, and doing the same for the two programs that
|
|
# do not take arguments at all.
|
|
#
|
|
# Copyright (C) 2026 Felitendo
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
set -uo pipefail
|
|
|
|
MCA_LIBDIR="${MCA_LIBDIR:-@LIBDIR@}"
|
|
|
|
for _mod in common config detect patch steam kde apply menu; do
|
|
# shellcheck source=/dev/null
|
|
if ! source "$MCA_LIBDIR/$_mod.sh"; then
|
|
printf 'middleclick-autoscroll: cannot load %s/%s.sh\n' "$MCA_LIBDIR" "$_mod" >&2
|
|
exit 14
|
|
fi
|
|
done
|
|
unset _mod
|
|
|
|
# Nothing here writes outside $HOME, so running it as root would patch root's
|
|
# own applications and leave the actual user without any.
|
|
if [[ $EUID -eq 0 && -z ${MCA_ALLOW_ROOT:-} ]]; then
|
|
printf 'middleclick-autoscroll: run this as your own user, not as root.\n' >&2
|
|
exit 2
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Commands
|
|
# ---------------------------------------------------------------------------
|
|
|
|
mca_do_enable() {
|
|
mca_config_set Enabled yes || {
|
|
mca_bad "$(mca_msg "Could not save the setting.")"
|
|
return 1
|
|
}
|
|
mca_config_load
|
|
|
|
mca_apply
|
|
|
|
if [[ $CFG_WATCH == yes ]]; then
|
|
if mca_watch_available; then
|
|
mca_watch_enable || mca_note "$(mca_msg "Could not start the watcher for newly installed applications.")"
|
|
else
|
|
mca_note "$(mca_msg "No systemd user session, so newly installed applications will not be picked up on their own.")"
|
|
fi
|
|
fi
|
|
|
|
mca_ok "$(mca_msg "Autoscroll is on for %d applications." "$MCA_N_ON")"
|
|
|
|
[[ -n $MCA_IN_MENU ]] \
|
|
|| mca_note "$(mca_msg "Applications that are already running pick this up when they are restarted.")"
|
|
}
|
|
|
|
mca_do_disable() {
|
|
mca_config_set Enabled no || {
|
|
mca_bad "$(mca_msg "Could not save the setting.")"
|
|
return 1
|
|
}
|
|
|
|
mca_revert
|
|
mca_watch_disable
|
|
|
|
mca_ok "$(mca_msg "Autoscroll is off and everything that was changed has been put back.")"
|
|
}
|
|
|
|
mca_do_apply() {
|
|
local rebuild=0 arg
|
|
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--rebuild) rebuild=1 ;;
|
|
--quiet) MCA_QUIET=1 ;;
|
|
esac
|
|
done
|
|
|
|
mca_config_load
|
|
|
|
if [[ $CFG_ENABLED != yes ]]; then
|
|
# Called by the watcher while switched off: there is nothing to do, and
|
|
# nothing to complain about either.
|
|
[[ -n $MCA_QUIET ]] && return 0
|
|
mca_note "$(mca_msg "Autoscroll is off. Turn it on first.")"
|
|
return 1
|
|
fi
|
|
|
|
# Start from a clean slate. Needed after a settings change, which can take
|
|
# an application out of scope as well as bring one in and where only a full
|
|
# undo can tell the difference, and it is what makes the repair a repair:
|
|
# whatever drifted is written again rather than left because it is "already
|
|
# applied".
|
|
#
|
|
# The watcher never does this. Rewriting files that are already correct
|
|
# would change their timestamps, and it is watching those directories.
|
|
if (( rebuild )); then
|
|
mca_revert
|
|
fi
|
|
|
|
mca_apply
|
|
|
|
if (( rebuild )); then
|
|
mca_ok "$(mca_msg "Applied again to %d applications." "$MCA_N_ON")"
|
|
[[ -n $MCA_IN_MENU ]] \
|
|
|| mca_say " $(mca_msg "Applications that are already running pick this up when they are restarted.")"
|
|
elif (( MCA_CHANGES )); then
|
|
mca_ok "$(mca_msg "Applied to %d applications." "$MCA_N_ON")"
|
|
[[ -n $MCA_IN_MENU ]] \
|
|
|| mca_say " $(mca_msg "Applications that are already running pick this up when they are restarted.")"
|
|
else
|
|
mca_ok "$(mca_msg "Already applied to %d applications." "$MCA_N_ON")"
|
|
fi
|
|
|
|
if [[ $CFG_WATCH == yes ]] && mca_watch_available; then
|
|
if mca_watch_enabled; then
|
|
mca_watch_refresh
|
|
else
|
|
mca_watch_enable || true
|
|
fi
|
|
elif [[ $CFG_WATCH != yes ]] && mca_watch_enabled; then
|
|
mca_watch_disable
|
|
fi
|
|
}
|
|
|
|
mca_do_status() {
|
|
mca_config_load
|
|
mca_head " $MCA_PRETTY"
|
|
mca_ui_status
|
|
printf '\n'
|
|
}
|
|
|
|
mca_do_list() {
|
|
local i route label pad
|
|
|
|
mca_config_load
|
|
mca_scan_once
|
|
mca_count_routes
|
|
|
|
if (( ${#MCA_IDS[@]} == 0 )); then
|
|
mca_note "$(mca_msg "No Chromium-based applications found.")"
|
|
return 0
|
|
fi
|
|
|
|
mca_head " $(mca_msg "Applications")"
|
|
|
|
for i in "${!MCA_IDS[@]}"; do
|
|
route="${MCA_ROUTES[i]}"
|
|
label="${MCA_NAMES[i]}"
|
|
pad=$(( 34 - ${#label} ))
|
|
(( pad < 0 )) && pad=0
|
|
printf ' %s%*s %s\n' "$label" "$pad" '' "$(mca_route_label "$route")"
|
|
done
|
|
printf '\n'
|
|
}
|
|
|
|
mca_do_help() {
|
|
cat <<- EOF
|
|
$MCA_PRETTY $MCA_VERSION
|
|
|
|
$(mca_msg "Usage: middleclick-autoscroll [command]")
|
|
|
|
$(mca_msg "Commands:")
|
|
enable $(mca_msg "Turn autoscroll on")
|
|
disable $(mca_msg "Turn it off and put everything back")
|
|
apply $(mca_msg "Apply to anything installed since the last run")
|
|
apply --rebuild $(mca_msg "Take everything back and apply it again")
|
|
status $(mca_msg "Show what is covered")
|
|
list $(mca_msg "List every application that was found")
|
|
-h, --help $(mca_msg "Show this help")
|
|
-V, --version $(mca_msg "Show the version")
|
|
|
|
$(mca_msg "Without a command an interactive menu is shown.")
|
|
EOF
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Dispatch
|
|
# ---------------------------------------------------------------------------
|
|
|
|
main() {
|
|
local cmd="${1:-}"
|
|
[[ $# -gt 0 ]] && shift
|
|
|
|
case "$cmd" in
|
|
enable) mca_do_enable "$@" ;;
|
|
disable) mca_do_disable "$@" ;;
|
|
apply|refresh) mca_do_apply "$@" ;;
|
|
status) mca_do_status "$@" ;;
|
|
list) mca_do_list "$@" ;;
|
|
|
|
-h|--help|help) mca_do_help ;;
|
|
-V|--version) printf '%s %s\n' "$MCA_NAME" "$MCA_VERSION" ;;
|
|
|
|
'') mca_ui_menu ;;
|
|
*)
|
|
mca_bad "$(mca_msg "Unknown command: %s" "$cmd")"
|
|
printf '\n'
|
|
mca_do_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|