docs: add claude.md and avoid dashes

This commit is contained in:
Felitendo committed 2026-09-21 14:00:02 +02:00
1 parent ab8c6477cb
commit 1042639a08
23 files changed
+220 -201

No files matched your search

+1 -1
View File
@@ -143,7 +143,7 @@ jobs:
printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import
else
echo "present=no" >> "$GITHUB_OUTPUT"
echo "::warning::No GPG_PRIVATE_KEY secret - the apt and dnf repositories were not updated. The packages are on the release."
echo "::warning::No GPG_PRIVATE_KEY secret, so the apt and dnf repositories were not updated. The packages are on the release."
exit 0
fi
echo "present=yes" >> "$GITHUB_OUTPUT"
+7
View File
@@ -0,0 +1,7 @@
# CLAUDE.md
## Style
- Use simple English: short sentences, common words.
- Avoid em dashes (—). Do not just swap them for "-" either. Rewrite the sentence instead, for
example with a comma, a colon, brackets or two sentences.
+7 -7
View File
@@ -1,4 +1,4 @@
# middleclick-autoscroll - build and install
# middleclick-autoscroll: build and install
#
# Everything here is plain shell; "building" only means compiling the gettext
# catalogs and rendering the man page. Both targets degrade to a no-op when
@@ -19,8 +19,8 @@ LOCALEDIR ?= $(DATADIR)/locale
MANDIR ?= $(DATADIR)/man
# Where systemd looks for user units. For a normal install into /usr this is
# asked of systemd itself, because the answer is not the same everywhere - a
# distribution that still keeps /lib separate from /usr/lib says so here - and
# asked of systemd itself, because the answer is not the same everywhere. A
# distribution that still keeps /lib separate from /usr/lib says so here. It is
# only guessed at when there is no systemd installed to ask.
#
# A build with a prefix of its own keeps the units under that prefix instead,
@@ -28,7 +28,7 @@ MANDIR ?= $(DATADIR)/man
# but only share for a home one: $XDG_DATA_HOME/systemd/user is a search path
# and ~/.local/lib/systemd/user is not, so an install into ~/.local that put
# the units in lib would leave the watcher impossible to enable. That prefix is
# the one an atomic distribution leaves a user - there is no writing to /usr on
# the one an atomic distribution leaves a user: there is no writing to /usr on
# Bazzite or Silverblue without layering a package and rebooting.
ifeq ($(PREFIX),/usr)
USERUNITDIR ?= $(shell pkg-config --variable=systemduserunitdir systemd 2>/dev/null || echo /usr/lib/systemd/user)
@@ -61,14 +61,14 @@ po/%.mo: po/%.po
ifdef MSGFMT
$(MSGFMT) --check --output-file=$@ $<
else
@echo "msgfmt not found - skipping $@"
@echo "msgfmt not found, skipping $@"
endif
$(MANPAGE): doc/middleclick-autoscroll.1.scd
ifdef SCDOC
$(SCDOC) < $< > $@
else
@echo "scdoc not found - skipping $@"
@echo "scdoc not found, skipping $@"
endif
# Syntax-check every shell file, and run shellcheck when it is available.
@@ -80,7 +80,7 @@ check:
shellcheck -x -e SC1090,SC1091 src/middleclick-autoscroll $(LIBS); \
echo "ok shellcheck"; \
else \
echo "shellcheck not found - skipped"; \
echo "shellcheck not found, skipped"; \
fi
@if command -v desktop-file-validate >/dev/null 2>&1; then \
echo "ok desktop-file-validate (nothing to check)"; \
+3 -3
View File
@@ -15,7 +15,7 @@ Just run `middleclick-autoscroll`. This will open the configuration TUI that loo
Autoscroll ON
Applications covered 11 of 13
Not identified 1 - see the applications list
Not identified 1 (see the applications list)
Steam ON
New applications ON
Middle-click paste off
@@ -46,7 +46,7 @@ Pressing `[3]` lets you see every app that was found and toggle each one individ
Slack off
Cursor cannot tell
Up/Down select - Space turns one on or off - q goes back
Up/Down: select, Space: turn on or off, q: back
```
You can also press `[4]` for more settings.
@@ -123,7 +123,7 @@ same thing manually.
AppImages get looked into as well. The payload is a squashfs image glued onto
the runtime, and squashfs keeps a small table with the name of every file in
there - so that table gets read and unpacked (a few kb, nothing is extracted
there. So that table gets read and unpacked (a few kb, nothing is extracted
and the thing is never run) and the Chromium files are looked for in it. An
Electron AppImage is covered like any other app; a Tauri one is left alone,
because WebKitGTK simply has no autoscroll to switch on.
+19 -19
View File
@@ -21,16 +21,16 @@ and puts that argument somewhere the application will actually read it, then
keeps doing so for anything installed later.
A browser is given *--enable-features=MiddleClickAutoscroll* instead. It asks
for the same feature - Blink generates a feature of that name for each of its
runtime flags - but it is not on the list of flags Chromium warns about, so the
browser does not put a bar reading "You are using an unsupported command-line
for the same feature, because Blink generates a feature of that name for each
of its runtime flags. But it is not on the list of flags Chromium warns about,
so the browser does not put a bar reading "You are using an unsupported command-line
flag" above every page. That spelling only works from Chromium 124 onwards,
which is why everything else keeps the first one: an application that embeds an
older Chromium, such as Steam's CEF, has no such bar to show anyway. Two
browsers know the feature under a name of their own and ignore Chromium's:
Helium, which is asked for *HeliumMiddleClickAutoscroll* as well, and Brave,
which is asked for *MiddelButtonClickAutoscroll* - spelled the way Brave spells
it. A name a browser does not know is ignored. It works on any distribution:
which is asked for *MiddelButtonClickAutoscroll* (spelled the way Brave spells
it). A name a browser does not know is ignored. It works on any distribution:
which of the routes below an application takes is read off its launcher, not
assumed from where the launcher came from.
@@ -55,7 +55,7 @@ is refused.
watcher calls; running it by hand is only needed when the watcher is off.
Entries left behind by an application that has since been uninstalled are
removed here too - the entry shadowing it lives in the user's home, where
removed here too. The entry shadowing it lives in the user's home, where
the package manager that removed the application cannot see it.
With *--rebuild* everything is taken back first and written again from
@@ -85,7 +85,7 @@ Two ways, chosen per application.
the supported way to pass arguments, it survives package upgrades, and it
applies to a launch from a terminal as much as one from the menu. A
feature list that is already in the file is extended rather than
duplicated - Chromium keeps only the last occurrence of such an option, so
duplicated. Chromium keeps only the last occurrence of such an option, so
a second one would switch the first one off.
Arch's Electron and Chromium packages all wrap their binaries this way, and
@@ -97,8 +97,8 @@ Two ways, chosen per application.
For applications that ship their own binary with no wrapper, and for
everything inside a Flatpak or a snap, a copy of the desktop entry with the
argument appended is written to _~/.local/share/applications_, where it
shadows the system one. Entries that already live there - AppImages, web
app shortcuts - are edited in place, with the original kept.
shadows the system one. Entries that already live there (AppImages, web
app shortcuts) are edited in place, with the original kept.
This is the route everything takes on the distributions whose Chromium
wrappers keep their equivalent file under _/etc_, where it is the system's
@@ -116,7 +116,7 @@ entry entirely. Those are patched in place as well.
Shortcuts on the desktop itself are patched in place too. Nothing in the XDG
search path looks at that folder, so a shortcut that lives only there would
otherwise be invisible - and Steam puts one there for every game somebody asks
otherwise be invisible. And Steam puts one there for every game somebody asks
for a shortcut to. The folder's name is translated, and the name in use is read
from _~/.config/user-dirs.dirs_ rather than guessed; the watcher is told about
it in a drop-in written when autoscroll is turned on.
@@ -134,14 +134,14 @@ _~/.local/share/Steam_ for Valve's own package and Arch's,
_~/.steam/debian-installation_ for Debian's, and the private tree of the
sandbox for the Flatpak and the snap. All of them are looked at.
Steam compares the installed files against its manifest at every start - by
size and timestamp rather than by content - and restores whatever differs. So
Steam compares the installed files against its manifest at every start (by
size and timestamp, not by content) and restores whatever differs. So
the patch is written to look untouched: the bytes the argument costs are taken
back out of the script's own comments and the timestamp is put back afterwards,
leaving a file exactly as long and exactly as old as Steam left it. A client
that checks its files finds nothing to repair, and the argument survives
however Steam was started - from the menu, from a game shortcut, from a
launcher like Heroic or Lutris, from a terminal.
however Steam was started: from the menu, from a game shortcut, from a
launcher like Heroic or Lutris, or from a terminal.
That is what has to work, because it is the only thing that does. A patch that
changes the length is never written, whatever else could be done to cover for
@@ -224,9 +224,9 @@ screen.
# WHAT HAS NO FLAG AT ALL
Autoscroll is a Blink feature, so only an application drawn by Blink can be
given it. An application built on WebKitGTK - which is what Tauri uses on
Linux, and GNOME Web, and anything else linked against libwebkit2gtk - is not
one of those. WebKit has no equivalent feature to ask for, on any command line
given it. An application built on WebKitGTK is not one of those. That
includes Tauri on Linux, GNOME Web, and anything else linked against
libwebkit2gtk. WebKit has no equivalent feature to ask for, on any command line
or in any configuration file.
Such an application is identified as what it is and then left out of the list
@@ -254,8 +254,8 @@ _~/.config/kwinrc_
_~/.cache/middleclick-autoscroll/detect_
Which programs were found to be Chromium, keyed by size and modification
time. Its first line says which version of the program wrote it, and a
file from an older one is ignored rather than trusted - an entry for a
file that has not changed would otherwise never be looked at again.
file from an older one is ignored rather than trusted. Otherwise an entry
for a file that has not changed would never be looked at again.
Safe to delete.
# ENVIRONMENT
+6 -6
View File
@@ -1,7 +1,7 @@
# Packaging and releases
The Makefile installs everything; these only wrap what it produced. That is
deliberate — a packaging script that lists the files again is a second
on purpose: a packaging script that lists the files again is a second
description of the layout, and two descriptions drift.
| | |
@@ -44,14 +44,14 @@ gh workflow run release.yml -f dry_run=true
Builds both packages, builds both repositories with a key generated on the
spot, checks the three signatures it wrote, and then installs the packages back
out of the repositories — apt on the runner, dnf in a Fedora container. Nothing
out of the repositories (apt on the runner, dnf in a Fedora container). Nothing
is pushed and no release is made. This is worth running after any change to the
packaging, because the alternative is finding out from a tag.
## Setting up the signing, once
The repositories are signed, so this needs a key. Make one that exists for
nothing else — not a personal key — and give it no passphrase: it lives as an
nothing else (not a personal key) and give it no passphrase. It lives as an
encrypted repository secret, and `rpmsign` cannot be handed a passphrase
unattended.
@@ -66,7 +66,7 @@ gpg --armor --export-secret-keys 'middleclick-autoscroll repository' \
Without the secret the workflow still builds both packages and attaches them to
the release; it says so in the log and leaves the repositories alone.
## Pointing Pages at it, once — and in this order
## Pointing Pages at it, once, in this order
The `gh-pages` branch does not exist until a release has put something on it,
and a branch that does not exist cannot be picked in the Pages settings. So:
@@ -77,8 +77,8 @@ and a branch that does not exist cannot be picked in the Pages settings. So:
root.
Doing it the other way round is a wall, and leaving Pages pointed at `main`
serves the source tree at the address the install instructions name — the key
and the indexes are 404 and nothing installs.
serves the source tree at the address the install instructions name. Then the
key and the indexes are 404 and nothing installs.
## What users end up with
+1 -1
View File
@@ -5,7 +5,7 @@
#
# Everything the package contains comes out of `make install`. This only wraps
# what that produced, so there is exactly one description of where a file goes
# and it is the Makefile - a packaging script that lists the files again is a
# and it is the Makefile. A packaging script that lists the files again is a
# second description, and the two drift.
#
# Needs: make, dpkg-deb, msgfmt (gettext), scdoc.
+3 -3
View File
@@ -3,12 +3,12 @@
# Refuses a release whose tag and Makefile disagree.
#
# The version is baked into the program at install time from the Makefile, and
# the packages take theirs from the same place - but the tag is what people see
# the packages take theirs from the same place. But the tag is what people see
# and what the release is named after. A tag that says something else produces
# a package called 1.0.4 containing a program that reports 1.0.3, and nothing
# would have complained.
#
# Anything that is not a v-tag - a run started by hand from a branch - is not a
# Anything that is not a v-tag (a run started by hand from a branch) is not a
# release and has nothing to check.
set -euo pipefail
@@ -19,7 +19,7 @@ ref="${1:-}"
case "$ref" in
v[0-9]*) ;;
*)
echo "not a release tag (${ref:-none}) - nothing to check against"
echo "not a release tag (${ref:-none}), nothing to check against"
exit 0
;;
esac
+1 -1
View File
@@ -8,7 +8,7 @@ Depends: bash (>= 4.2), coreutils, findutils, grep, sed, mawk | gawk | original-
Recommends: gettext-base, systemd, desktop-file-utils
Homepage: https://github.com/LoonixTools/middleclick-autoscroll
Description: middle-click autoscroll for Chromium-based applications
Blink - the engine inside Chromium, Electron and CEF - has had Windows-style
Blink (the engine inside Chromium, Electron and CEF) has had Windows-style
autoscroll for years: hold the middle mouse button, move the pointer, the page
scrolls. On Linux it is switched off, because middle click is already taken by
primary-selection paste.
+4 -4
View File
@@ -64,9 +64,9 @@
<h1>middleclick-autoscroll</h1>
<p class="lead">
Middle-click autoscroll — hold the middle mouse button, move the pointer, the
page scrolls — in every Chromium-based application on the system, and in
anything installed later.
Middle-click autoscroll in every Chromium-based application on the system,
and in anything installed later: hold the middle mouse button, move the
pointer, and the page scrolls.
</p>
<p>
@@ -103,7 +103,7 @@ sudo zypper install middleclick-autoscroll</code></pre>
<p>
That is the whole setup. Nothing else has to be configured and no file has to
be edited. Run <code>middleclick-autoscroll disable</code> before removing the
package — it puts back everything that was changed.
package. It puts back everything that was changed.
</p>
<footer>
+1 -1
View File
@@ -11,7 +11,7 @@
# Usage: publish-repos.sh <gh-pages checkout> <directory of new packages>
#
# Needs: dpkg-dev, apt-utils, createrepo-c, gpg, and a secret key already
# imported - its id is taken from the keyring.
# imported. Its id is taken from the keyring.
set -euo pipefail
+1 -1
View File
@@ -33,7 +33,7 @@ Recommends: systemd
Recommends: desktop-file-utils
%description
Blink - the engine inside Chromium, Electron and CEF - has had Windows-style
Blink (the engine inside Chromium, Electron and CEF) has had Windows-style
autoscroll for years: hold the middle mouse button, move the pointer, the page
scrolls. On Linux it is switched off, because middle click is already taken by
primary-selection paste.
+36 -25
View File
@@ -5,7 +5,8 @@
msgid ""
msgstr ""
"Project-Id-Version: middleclick-autoscroll 1.0.3\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/middleclick-autoscroll/issues\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/middleclick-autoscroll/"
"issues\n"
"POT-Creation-Date: 2026-08-16 00:00+0200\n"
"PO-Revision-Date: 2026-08-16 00:00+0200\n"
"Last-Translator: Felitendo\n"
@@ -43,7 +44,6 @@ msgstr "nicht erkennbar"
msgid "not patched yet"
msgstr "noch nicht gepatcht"
#. Status block
msgid "Autoscroll"
msgstr "Autoscroll"
@@ -57,8 +57,8 @@ msgstr "%d von %d"
msgid "Not identified"
msgstr "Nicht erkannt"
msgid "%d - see the applications list"
msgstr "%d – siehe Anwendungsliste"
msgid "%d (see the applications list)"
msgstr "%d (siehe Anwendungsliste)"
msgid "Steam"
msgstr "Steam"
@@ -75,7 +75,6 @@ msgstr "Zuletzt angewendet"
msgid "Applications pick this up the next time they are started."
msgstr "Anwendungen übernehmen das beim nächsten Start."
#. Menu
msgid "Turn autoscroll on or off"
msgstr "Autoscroll ein- oder ausschalten"
@@ -95,7 +94,6 @@ msgstr "Beenden"
msgid "Press any key to continue..."
msgstr "Beliebige Taste drücken …"
#. Settings
msgid "Electron and CEF applications"
msgstr "Electron- und CEF-Anwendungen"
@@ -124,8 +122,8 @@ msgstr "Auf neu installierte Anwendungen anwenden"
msgid "Additional Chromium arguments"
msgstr "Zusätzliche Chromium-Argumente"
msgid "Up/Down select - Space or Right changes - q goes back"
msgstr "Hoch/Runter wählt – Leertaste oder Rechts ändert – q geht zurück"
msgid "Up/Down: select, Space or Right: change, q: back"
msgstr "Hoch/Runter: wählen, Leertaste oder Rechts: ändern, q: zurück"
msgid "Arguments separated by spaces, empty for none:"
msgstr "Argumente mit Leerzeichen getrennt, leer für keine:"
@@ -133,7 +131,6 @@ msgstr "Argumente mit Leerzeichen getrennt, leer für keine:"
msgid "Could not save the setting."
msgstr "Einstellung konnte nicht gespeichert werden."
#. Applications screen
msgid "Looking at the installed applications..."
msgstr "Installierte Anwendungen werden durchgesehen …"
@@ -142,27 +139,34 @@ msgid "No Chromium-based applications found."
msgstr "Keine Chromium-basierten Anwendungen gefunden."
msgid "Anything not identified is left alone until it is turned on here."
msgstr "Nicht erkannte Anwendungen bleiben unangetastet, bis sie hier eingeschaltet werden."
msgstr ""
"Nicht erkannte Anwendungen bleiben unangetastet, bis sie hier eingeschaltet "
"werden."
msgid "Autoscroll is off - this is what would be covered."
msgstr "Autoscroll ist aus – das hier wäre abgedeckt."
msgid "Up/Down select - Space turns one on or off - q goes back"
msgstr "Hoch/Runter wählt – Leertaste schaltet einzeln ein oder aus – q geht zurück"
msgid "Autoscroll is off. This is what would be covered."
msgstr "Autoscroll ist aus. Das hier wäre abgedeckt."
msgid "Up/Down: select, Space: turn on or off, q: back"
msgstr "Hoch/Runter: wählen, Leertaste: ein- oder ausschalten, q: zurück"
#. Results
msgid "Autoscroll is on for %d applications."
msgstr "Autoscroll ist für %d Anwendungen an."
msgid "Applications that are already running pick this up when they are restarted."
msgid ""
"Applications that are already running pick this up when they are restarted."
msgstr "Bereits laufende Anwendungen übernehmen das nach einem Neustart."
msgid "Could not start the watcher for newly installed applications."
msgstr "Die Überwachung neu installierter Anwendungen konnte nicht gestartet werden."
msgstr ""
"Die Überwachung neu installierter Anwendungen konnte nicht gestartet werden."
msgid "No systemd user session - newly installed applications will not be picked up on their own."
msgstr "Keine systemd-Benutzersitzung – neu installierte Anwendungen werden nicht von selbst erfasst."
msgid ""
"No systemd user session, so newly installed applications will not be picked "
"up on their own."
msgstr ""
"Keine systemd-Benutzersitzung, daher werden neu installierte Anwendungen "
"nicht von selbst erfasst."
msgid "Autoscroll is off and everything that was changed has been put back."
msgstr "Autoscroll ist aus, alle Änderungen wurden zurückgenommen."
@@ -179,16 +183,24 @@ msgstr "Auf %d Anwendungen angewendet."
msgid "Already applied to %d applications."
msgstr "Bereits auf %d Anwendungen angewendet."
msgid "Steam starts its interface in a way this version cannot change without Steam noticing; leaving it alone."
msgstr "Steam startet seine Oberfläche auf eine Art, die diese Version nicht ändern kann, ohne dass Steam es merkt; Steam bleibt unangetastet."
msgid ""
"Steam starts its interface in a way this version cannot change without Steam "
"noticing; leaving it alone."
msgstr ""
"Steam startet seine Oberfläche auf eine Art, die diese Version nicht ändern "
"kann, ohne dass Steam es merkt; Steam bleibt unangetastet."
msgid "Steam's interface cannot be given the flag without leaving a file Steam would reinstall; the change has been taken back."
msgstr "Steams Oberfläche lässt sich das Flag nicht geben, ohne eine Datei zu hinterlassen, die Steam neu installieren würde; die Änderung wurde zurückgenommen."
msgid ""
"Steam's interface cannot be given the flag without leaving a file Steam "
"would reinstall; the change has been taken back."
msgstr ""
"Steams Oberfläche lässt sich das Flag nicht geben, ohne eine Datei zu "
"hinterlassen, die Steam neu installieren würde; die Änderung wurde "
"zurückgenommen."
msgid "Middle click stops pasting at the next login."
msgstr "Mittelklick fügt ab der nächsten Anmeldung nichts mehr ein."
#. Help
msgid "Usage: middleclick-autoscroll [command]"
msgstr "Aufruf: middleclick-autoscroll [Befehl]"
@@ -226,7 +238,6 @@ msgstr "Ohne Befehl wird ein interaktives Menü angezeigt."
msgid "Unknown command: %s"
msgstr "Unbekannter Befehl: %s"
#. Time
msgid "never"
msgstr "nie"
+17 -16
View File
@@ -5,7 +5,8 @@
msgid ""
msgstr ""
"Project-Id-Version: middleclick-autoscroll 1.0.3\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/middleclick-autoscroll/issues\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/middleclick-autoscroll/"
"issues\n"
"POT-Creation-Date: 2026-08-16 00:00+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
@@ -43,7 +44,6 @@ msgstr ""
msgid "not patched yet"
msgstr ""
#. Status block
msgid "Autoscroll"
msgstr ""
@@ -57,7 +57,7 @@ msgstr ""
msgid "Not identified"
msgstr ""
msgid "%d - see the applications list"
msgid "%d (see the applications list)"
msgstr ""
msgid "Steam"
@@ -75,7 +75,6 @@ msgstr ""
msgid "Applications pick this up the next time they are started."
msgstr ""
#. Menu
msgid "Turn autoscroll on or off"
msgstr ""
@@ -95,7 +94,6 @@ msgstr ""
msgid "Press any key to continue..."
msgstr ""
#. Settings
msgid "Electron and CEF applications"
msgstr ""
@@ -124,7 +122,7 @@ msgstr ""
msgid "Additional Chromium arguments"
msgstr ""
msgid "Up/Down select - Space or Right changes - q goes back"
msgid "Up/Down: select, Space or Right: change, q: back"
msgstr ""
msgid "Arguments separated by spaces, empty for none:"
@@ -133,7 +131,6 @@ msgstr ""
msgid "Could not save the setting."
msgstr ""
#. Applications screen
msgid "Looking at the installed applications..."
msgstr ""
@@ -144,24 +141,26 @@ msgstr ""
msgid "Anything not identified is left alone until it is turned on here."
msgstr ""
msgid "Autoscroll is off - this is what would be covered."
msgid "Autoscroll is off. This is what would be covered."
msgstr ""
msgid "Up/Down select - Space turns one on or off - q goes back"
msgid "Up/Down: select, Space: turn on or off, q: back"
msgstr ""
#. Results
msgid "Autoscroll is on for %d applications."
msgstr ""
msgid "Applications that are already running pick this up when they are restarted."
msgid ""
"Applications that are already running pick this up when they are restarted."
msgstr ""
msgid "Could not start the watcher for newly installed applications."
msgstr ""
msgid "No systemd user session - newly installed applications will not be picked up on their own."
msgid ""
"No systemd user session, so newly installed applications will not be picked "
"up on their own."
msgstr ""
msgid "Autoscroll is off and everything that was changed has been put back."
@@ -179,16 +178,19 @@ msgstr ""
msgid "Already applied to %d applications."
msgstr ""
msgid "Steam starts its interface in a way this version cannot change without Steam noticing; leaving it alone."
msgid ""
"Steam starts its interface in a way this version cannot change without Steam "
"noticing; leaving it alone."
msgstr ""
msgid "Steam's interface cannot be given the flag without leaving a file Steam would reinstall; the change has been taken back."
msgid ""
"Steam's interface cannot be given the flag without leaving a file Steam "
"would reinstall; the change has been taken back."
msgstr ""
msgid "Middle click stops pasting at the next login."
msgstr ""
#. Help
msgid "Usage: middleclick-autoscroll [command]"
msgstr ""
@@ -226,7 +228,6 @@ msgstr ""
msgid "Unknown command: %s"
msgstr ""
#. Time
msgid "never"
msgstr ""
+5 -5
View File
@@ -5,7 +5,7 @@ Documentation=man:middleclick-autoscroll(1)
[Path]
# Every way an application can turn up: a package, a Flatpak, a snap, something
# installed by hand. Watching where the launchers land means there is no hook
# to write per package manager - pacman, apt, dnf, zypper, flatpak, snapd and
# to write per package manager: pacman, apt, dnf, zypper, flatpak, snapd and
# an AppImage manager all end up here.
#
# A directory that does not exist on this system costs nothing: systemd watches
@@ -23,10 +23,10 @@ PathModified=/run/current-system/sw/share/applications
PathModified=%h/.nix-profile/share/applications
PathModified=%h/.guix-profile/share/applications
# The desktop folder is watched too - Steam writes a shortcut there for every
# game somebody asks for one, and starting a game is a Steam start - but its
# name is translated and cannot be written down here. `enable` adds it in a
# drop-in, from the name this system uses.
# The desktop folder is watched too. Steam writes a shortcut there for every
# game somebody asks for one, and starting a game is a Steam start. But the
# folder's name is translated and cannot be written down here. `enable` adds it
# in a drop-in, from the name this system uses.
# Steam replaces the script that starts its interface on every client update,
# which takes the patch with it. Where that installation lives depends on how
+5 -5
View File
@@ -4,7 +4,7 @@
#
# The routing lives in mca_route and is used twice: once by mca_apply to patch
# and once by the applications screen to show what would happen. Keeping it in
# one function is what makes that screen trustworthy - it is not a description
# one function is what makes that screen trustworthy: it is not a description
# of the behaviour, it is the behaviour.
MCA_CHANGES=0
@@ -56,7 +56,7 @@ mca_route() {
# mca_apply
# Brings everything into line with the current settings. Safe to run as often
# as it likes to be - it writes only what differs, which is what keeps the
# as it likes to be. It writes only what differs, which is what keeps the
# watcher from chasing its own changes.
mca_apply() {
local i id file prog kind packaging route steam_done=0
@@ -114,7 +114,7 @@ mca_apply() {
esac
done
# Steam is worth patching even when its desktop entry is missing - a user
# Steam is worth patching even when its desktop entry is missing. A user
# who starts it from a script or a game launcher still gets the interface.
if [[ $CFG_STEAM == yes ]] && (( ! steam_done )) && mca_steam_installed; then
mca_steam_apply
@@ -191,8 +191,8 @@ mca_watch_enabled() {
# _mca_watch_dropin_write
# Returns 0 when the drop-in changed and systemd has to be told, 1 when it was
# already right - the same contract as mca_write_if_changed, and for the same
# reason: the watcher runs after every desktop entry that appears anywhere on
# already right. That is the same contract as mca_write_if_changed, for the
# same reason: the watcher runs after every desktop entry that appears anywhere on
# the system, and a daemon-reload each time would be absurd.
_mca_watch_dropin_write() {
local dir file="$MCA_UNIT_DROPIN/desktop.conf" content
+9 -9
View File
@@ -3,7 +3,7 @@
# Paths, translations, output helpers and the change ledger.
#
# Everything here runs unprivileged. This tool only ever writes inside the
# user's own home - flag files, desktop entries, Steam's own scripts - so there
# user's own home (flag files, desktop entries, Steam's own scripts), so there
# is no system state to guard and nothing that needs root.
MCA_VERSION="@VERSION@"
@@ -19,7 +19,7 @@ MCA_PRETTY="Middle-Click Autoscroll"
#
# --enable-blink-features=MiddleClickAutoscroll is the one that works
# everywhere, and the only one that works in the Chromium versions embedded
# applications ship - Steam's CEF, an Electron a few years old, anything
# applications ship: Steam's CEF, an Electron a few years old, anything
# before Chromium 124. A browser started with it puts a yellow bar above the
# page saying an unsupported command line flag is in use, because Chromium
# keeps a list of flags worth warning about and this is on it.
@@ -27,7 +27,7 @@ MCA_PRETTY="Middle-Click Autoscroll"
# --enable-features=MiddleClickAutoscroll is not on that list, so a browser
# started with it says nothing. Blink generates a feature of the same name
# for every one of its runtime flags, which is what makes the two the same
# request - but only since Chromium 124. Before that the name means nothing
# request. But only since Chromium 124. Before that the name means nothing
# and is ignored without a word.
#
# So a browser, which is the only thing that shows the bar and the one thing
@@ -38,7 +38,7 @@ MCA_FLAG="--enable-blink-features=MiddleClickAutoscroll"
# Two browsers do not answer to the Chromium name. Helium ships the feature
# under its own name and sets the runtime flag from that alone. Brave takes
# the generated feature away and switches the flag on from one of its own,
# spelled MiddelButtonClickAutoscroll - the typo is in Brave's source, and the
# spelled MiddelButtonClickAutoscroll. The typo is in Brave's source, and the
# correct spelling does nothing. So browsers are asked for all three. A name a
# browser does not know is ignored, which is what makes one list safe to hand
# to all of them.
@@ -87,7 +87,7 @@ MCA_BACKUPDIR="${MCA_STATEDIR}/backup"
MCA_LEDGER="${MCA_STATEDIR}/ledger"
# The folder the desktop itself shows. Nothing in the XDG search path looks at
# it, so an entry that lives only there is invisible to a scan - and a game
# it, so an entry that lives only there is invisible to a scan. A game
# shortcut dragged onto the desktop is exactly that.
#
# Its name is translated: Schreibtisch, Bureau, Escritorio. The name in use is
@@ -217,8 +217,8 @@ fi
# Set by mca_bad and mca_note. The menu redraws straight after an action, which
# would wipe the screen; this marks that something was printed the user still
# has to read. A plain success needs no acknowledgement - the status block at
# the top of the menu already shows the new state.
# has to read. A plain success needs no acknowledgement, because the status
# block at the top of the menu already shows the new state.
MCA_UI_NEEDS_ACK=''
# --quiet silences progress chatter; errors still go to stderr. Used by the
@@ -275,7 +275,7 @@ mca_state_write() {
# ---------------------------------------------------------------------------
# The change ledger
# ---------------------------------------------------------------------------
# Reverting by pattern - "delete every desktop entry that mentions the flag" -
# Reverting by pattern ("delete every desktop entry that mentions the flag")
# would also delete entries the user wrote by hand. So every change is recorded
# instead, and `revert` replays the ledger backwards.
#
@@ -289,7 +289,7 @@ mca_state_write() {
#
# The kinds differ in how they are undone: a backup is restored wholesale, a
# flag file only loses the one line that was added to it, and kwinrc gets one
# key written back - it is a file KDE writes to itself, and putting a whole
# key written back. It is a file KDE writes to itself, and putting a whole
# copy of it back would take everything else settled since with it.
mca_ledger_add() {
+51 -51
View File
@@ -4,7 +4,7 @@
#
# The detection is deliberately conservative. A wrong "yes" appends an unknown
# argument to something that is not Chromium, and plenty of programs treat an
# unrecognised argument as a file name to open - so every rule here is a
# unrecognised argument as a file name to open. So every rule here is a
# positive one, and anything that cannot be identified is reported as unknown
# rather than guessed at.
@@ -13,7 +13,7 @@
# swiftshader libraries) and plain CEF (libcef).
#
# Deliberately not in here: libEGL.so and libffmpeg.so. Chromium ships both, but
# so does the system - /usr/lib/libEGL.so exists on any machine with Mesa - and
# so does the system (/usr/lib/libEGL.so exists on any machine with Mesa), and
# a marker that can be somebody else's file is not a marker.
MCA_MARKERS=(
chrome_crashpad_handler chrome-sandbox chrome_100_percent.pak
@@ -22,14 +22,14 @@ MCA_MARKERS=(
)
# The markers that still mean something when the whole of a tree is searched
# rather than just the directory the binary sits in - inside a Flatpak, a snap
# or an AppImage, where there is no "next to the binary" to look at.
# rather than just the directory the binary sits in. That is the case inside a
# Flatpak, a snap or an AppImage, where there is no "next to the binary".
#
# Three of the names above are missing here on purpose. icudtl.dat is ICU's
# data file and not Chromium's: a Flutter application ships one in data/, and
# a whole-tree search would find it. snapshot_blob.bin and resources.pak are
# the same kind of shared name. Next to a binary they are still evidence,
# because nothing but Chromium unpacks its payload there - a few directories
# because nothing but Chromium unpacks its payload there. A few directories
# deeper they are not.
MCA_MARKERS_STRICT=(
chrome_crashpad_handler chrome-sandbox chrome_100_percent.pak
@@ -81,7 +81,7 @@ MCA_SCRIPT_HINTS='ELECTRON_|app\.asar|chrome-sandbox|libcef|enable-blink-feature
# ---------------------------------------------------------------------------
# Where Flatpak and snapd put the launchers they export. Both add these to
# XDG_DATA_DIRS themselves, through a file in /etc/profile.d - but only for a
# XDG_DATA_DIRS themselves, through a file in /etc/profile.d. But only for a
# session that was started after they were installed, and only for a session
# manager that reads it at all. They are appended, after everything XDG names,
# so a directory that is already in the search path keeps its own position and
@@ -93,7 +93,7 @@ mca_extra_desktop_dirs() {
/var/lib/snapd/desktop/applications
}
# The directories a desktop entry can come from, most specific first - which is
# The directories a desktop entry can come from, most specific first. This is
# also XDG lookup order, so the first file found for an id is the one that is
# actually used.
mca_desktop_dirs() {
@@ -155,7 +155,7 @@ _mca_desktop_read() {
# mca_exec_program <exec line>
# The program a desktop entry actually starts: the first token that is not an
# environment prefix, resolved to an absolute path. The result is left in
# MCA_PROG rather than printed - the scan calls this for every desktop entry on
# MCA_PROG rather than printed. The scan calls this for every desktop entry on
# the system, and a command substitution each time is a fork each time.
#
# Fails for entries this tool has no safe way to rewrite: anything routed
@@ -231,7 +231,7 @@ mca_exec_flatpak_id() {
# Whether an entry starts something inside Steam rather than starting Steam
# itself: it carries a steam:// address of its own. Steam writes one of those
# for every game somebody asks for a shortcut to, and the client's own entry
# never has one - it takes an address from the outside, through %U.
# never has one. It takes an address from the outside, through %U.
mca_exec_is_steam_link() {
local line="$1" prog="$2"
@@ -251,7 +251,7 @@ _mca_prog_is_steam_name() {
# _mca_prog_is_steam_wrapper <program>
# Whether a script in front of the client is a way of starting Steam. People
# put one there to add a switch of their own, and an entry pointing at it is a
# Steam start like any other - but the script is not named after Steam, so
# Steam start like any other. But the script is not named after Steam, so
# nothing above recognises it.
#
# Getting this wrong is worse than it sounds: such a script tends to mention
@@ -282,8 +282,8 @@ _mca_prog_is_steam_wrapper() {
# mca_prog_is_steam <program>
# Whether running this program starts the Steam client. Every packaging is in
# here and every name Valve and the distributions give the launcher, because
# the answer decides whether an entry gets Steam's own switch - and an entry
# that starts Steam without it undoes the web helper patch on the way up.
# the answer decides whether an entry gets Steam's own switch. An entry that
# starts Steam without it undoes the web helper patch on the way up.
#
# The program is what a scan leaves behind: an absolute path for a native
# install, flatpak:<id> or snap:<name> for the other two.
@@ -328,7 +328,7 @@ _mca_stat_batch() {
# The first line of the cache file, and the reason it is there: the verdicts
# below it are keyed on size and mtime, so an entry for a file that has not
# changed is never looked at again. A cache written when a verdict meant
# something else - before an AppImage could come out as anything but "no" -
# something else (before an AppImage could come out as anything but "no")
# would therefore keep answering the old way forever. Bumping this is how such
# a cache gets dropped instead.
MCA_CACHE_FORMAT='# middleclick-autoscroll detect 2'
@@ -380,7 +380,7 @@ _mca_has_markers() {
[[ $dir == "$s" ]] && return 1
done
for s in "${MCA_SYSTEM_DIR_GLOBS[@]}"; do
# Unquoted on purpose - these are patterns, not names.
# Unquoted on purpose: these are patterns, not names.
# shellcheck disable=SC2053
[[ $dir == $s ]] && return 1
done
@@ -396,7 +396,7 @@ _mca_has_markers() {
# The same question for a whole tree, which is the shape a Flatpak, a snap and
# an unpacked AppImage come in: everything the application ships is somewhere
# under one root and there is no single directory that is "next to the binary".
# Hence the narrower list - see MCA_MARKERS_STRICT.
# Hence the narrower list, see MCA_MARKERS_STRICT.
_mca_find_markers() {
local root="$1" depth="$2" m
local -a names=()
@@ -423,9 +423,9 @@ declare -A MCA_SCRIPT_VARS=()
# The text with $NAME and ${NAME} replaced by what the script assigned to them,
# left in MCA_SUBST.
#
# Fails as soon as something turns up that only a running shell could work out
# - a positional parameter, a name the script never set, a default value. That
# is the point: an unresolvable path has to come out as no path at all, never
# Fails as soon as something turns up that only a running shell could work out,
# like a positional parameter, a name the script never set or a default value.
# That is the point: an unresolvable path has to come out as no path at all, never
# as a wrong one.
MCA_SUBST=''
@@ -465,8 +465,8 @@ _mca_script_subst() {
# openSUSE all set the directory and the program name into variables at the top
# of the script and end on `exec -a "$APPNAME" "$LIBDIR/$APPNAME"`. Without
# resolving those there is nothing to follow, and the answer would have to come
# from the hint scan - a weaker kind of evidence than finding the binary and
# its markers.
# from the hint scan, which is weaker evidence than finding the binary and its
# markers.
_mca_script_target() {
local script="$1" line tok name val skip=0
local -a tokens
@@ -537,10 +537,10 @@ _mca_script_target() {
# mca_flags_candidates <program>
# The flag files a launcher reads, in the order it reads them, taken from the
# launcher itself rather than assumed from the distribution. Where the wrappers
# follow that convention - Arch's Electron and Chromium packages do, and take
# extra arguments from $XDG_CONFIG_HOME/<name>-flags.conf - it is a far better
# place to inject than a desktop entry: it survives package updates and it
# launcher itself rather than assumed from the distribution. Arch's Electron
# and Chromium packages follow that convention and take extra arguments from
# $XDG_CONFIG_HOME/<name>-flags.conf. Where the wrappers do that, it is a far
# better place to inject than a desktop entry: it survives package updates and it
# applies to a launch from the terminal too. Where they do not, this finds
# nothing and the caller falls back to the desktop entry.
mca_flags_candidates() {
@@ -553,7 +553,7 @@ mca_flags_candidates() {
# A wrapper that only execs another wrapper (heroic -> electron43) inherits
# that one's flag files, plus the specific name it builds from a variable
# at runtime and therefore never writes down - which is why that one is
# at runtime and therefore never writes down. That is why that one is
# derived from the target's own name rather than found.
#
# It is derived only once the target has shown that it reads a flag file at
@@ -575,7 +575,7 @@ mca_flags_candidates() {
# Looking inside an AppImage
# ---------------------------------------------------------------------------
#
# An AppImage is the AppImage runtime - an ordinary ELF executable - with a
# An AppImage is the AppImage runtime (an ordinary ELF executable) with a
# squashfs image appended to it. The payload is compressed, so nothing the
# application ships is on disk where the marker check could find it, and for a
# long time that made every AppImage a "cannot tell".
@@ -594,7 +594,7 @@ mca_flags_candidates() {
# _mca_bytes <file> <offset> <count>
# Count bytes from an offset, as numbers, in MCA_BYTES. od rather than a shell
# read because a variable cannot hold a NUL byte and these headers are full of
# them - and a whole header at a time rather than a field at a time, because
# them. And a whole header at a time rather than a field at a time, because
# the first question below is asked about every program on the system and one
# od per field would be four forks per program.
MCA_BYTES=()
@@ -627,7 +627,7 @@ _mca_slice() {
#
# Fails for the all-ones value squashfs writes down for a table that is not in
# the image, which is a case the callers below have to tell from a real offset
# and bash arithmetic - signed, 64-bit - cannot represent.
# and bash arithmetic (signed, 64-bit) cannot represent.
MCA_WORD=0
_mca_word() {
@@ -650,7 +650,7 @@ _mca_word() {
#
# Searching for the squashfs magic instead would not be: the runtime carries a
# copy of it in its own code. Neither is the AppImage magic at byte 8 of the
# ELF header a way in - it is there to be zeroed, and a build pipeline that
# ELF header a way in. It is there to be zeroed, and a build pipeline that
# does not want its image picked up by a desktop integration daemon does
# exactly that. So the offset is computed for any ELF at all and the caller
# finds out whether there is an image at it.
@@ -700,7 +700,7 @@ _mca_inflate() {
1)
# squashfs stores a zlib stream and gzip only reads its own
# container, but underneath both are the same deflate data with a
# different wrapper around it - so the wrapper is swapped: zlib's
# different wrapper around it. So the wrapper is swapped: zlib's
# two header bytes are dropped and a minimal gzip header put in
# front. gzip then writes every byte of the block and complains
# about the trailer it did not get, which is why its status is
@@ -734,10 +734,10 @@ _mca_inflate() {
# describe them, and a name is all the caller is looking for.
#
# Fails unless the walk lands exactly on the end of the table. That is the
# integrity check - the block sizes adding up to the table's own length is
# what says the fields were read from a real superblock and that the output is
# the whole of the names rather than some of them - and it is why the caller
# has to collect this before trusting it, never pipe it.
# integrity check: the block sizes adding up to the table's own length is what
# says the fields were read from a real superblock, and that the output is the
# whole of the names rather than some of them. It is also why the caller has
# to collect this before trusting it, never pipe it.
_mca_squashfs_names() {
local file="$1" base="$2"
local comp dir_start end field header size pos
@@ -750,9 +750,9 @@ _mca_squashfs_names() {
(( dir_start > 0 )) || return 1
# Where the names stop: the first table squashfs writes after them. Which
# one that is depends on the image - there is no fragment table when
# one that is depends on the image. There is no fragment table when
# nothing was packed into a fragment, and no export table unless it was
# asked for - so they are tried in the order they are written and the
# asked for. So they are tried in the order they are written and the
# first one that is actually there wins. bytes_used closes the list for an
# image that has none of them.
end=0
@@ -815,14 +815,14 @@ _mca_appimage_verdict() {
&& MCA_BYTES[2] == 113 && MCA_BYTES[3] == 115 )) || return 0
# From here on there is an image, so the worst this can end on is "cannot
# tell" - never "no", which would be an answer about contents that were
# tell". Never "no", which would be an answer about contents that were
# never read.
MCA_APPIMAGE=unknown
names="$(mktemp "${TMPDIR:-/tmp}/mca-names.XXXXXX")" || return 0
# Nothing at all in the table means every block failed to inflate - a
# compressor whose tool is not installed - which is a "cannot tell" too.
# Nothing at all in the table means every block failed to inflate (a
# compressor whose tool is not installed). That is a "cannot tell" too.
if _mca_squashfs_names "$file" "$base" > "$names" 2>/dev/null \
&& [[ -s $names ]]
then
@@ -900,7 +900,7 @@ mca_detect_verdict() {
# mca_is_chromium <program>
# Succeeds when the program is a Chromium, CEF or Electron process. "Cannot
# tell" is not that, so it fails here - anything that has to treat the two
# tell" is not that, so it fails here. Anything that has to treat the two
# differently asks mca_detect_verdict instead.
mca_is_chromium() {
mca_detect_verdict "$1"
@@ -931,13 +931,13 @@ _mca_detect_uncached() {
fi
# A binary. Everything Chromium ships is unpacked next to it, either in the
# same directory or - for /opt/thing/bin/Thing layouts - one level up.
# same directory or (for /opt/thing/bin/Thing layouts) one level up.
dir="$(dirname -- "$real")"
_mca_has_markers "$dir" && return 0
[[ ${dir##*/} == bin ]] && _mca_has_markers "${dir%/*}" && return 0
# An AppImage keeps all of that inside a filesystem appended to itself, so
# there is nothing next to the binary to find - but the names of everything
# there is nothing next to the binary to find. But the names of everything
# in there can be read, and that settles it either way.
_mca_appimage_verdict "$real"
case "$MCA_APPIMAGE" in
@@ -950,8 +950,8 @@ _mca_detect_uncached() {
grep -qaFm1 -- 'enable-blink-features' "$real" 2>/dev/null && return 0
grep -qaFm1 -- 'CHROME_VERSION_EXTRA' "$real" 2>/dev/null && return 0
# What is left is an image that could not be read - an unsupported
# compressor - or the older AppImage layout, which is an ISO9660 filesystem
# What is left is an image that could not be read (an unsupported
# compressor) or the older AppImage layout, which is an ISO9660 filesystem
# and has no name table of this shape at all. Either way the answer is not
# "no", it is "nobody looked".
if [[ $MCA_APPIMAGE == unknown || $real == *.AppImage || $real == *.appimage ]]; then
@@ -993,7 +993,7 @@ mca_scan() {
MCA_PACKAGING=()
# Pass one: read the entries and work out what each of them starts. No
# detection yet - that needs a stat per program, and those are collected so
# detection yet: that needs a stat per program, and those are collected so
# they can be asked for all at once.
while IFS= read -r dir; do
[[ -d $dir ]] || continue
@@ -1031,8 +1031,8 @@ mca_scan() {
fi
# The shortcuts Steam writes for single games are not
# applications of their own - a game is whatever engine it was
# built with, and none of those reads a Chromium argument - and
# applications of their own. A game is whatever engine it was
# built with, and none of those reads a Chromium argument. And
# starting the client through one needs nothing on its command
# line either.
mca_exec_is_steam_link "$exec_line" "$prog" && continue
@@ -1047,8 +1047,8 @@ mca_scan() {
MCA_STAT=()
_mca_stat_batch "${c_stat[@]}"
# Pass two: decide what each one is. What it does - an application or a
# browser - and how it was packaged are two separate questions: a Chromium
# Pass two: decide what each one is. What it does (an application or a
# browser) and how it was packaged are two separate questions: a Chromium
# installed as a snap is still a browser, and somebody who has turned
# browsers off means that one too.
for i in "${!c_ids[@]}"; do
@@ -1131,8 +1131,8 @@ mca_desktop_is_browser() {
}
# mca_snap_name <program>
# The snap an executable belongs to, left in MCA_PROG - assigned rather than
# printed for the same reason mca_exec_program is: the scan asks this about
# The snap an executable belongs to, left in MCA_PROG. It is assigned rather
# than printed for the same reason mca_exec_program is: the scan asks this about
# every desktop entry on the system, and a command substitution per entry is a
# fork per entry.
#
+5 -5
View File
@@ -6,7 +6,7 @@
# autoscroll on, Blink stops pasting the primary selection on middle click,
# because the button is doing something else now. Everywhere else on the
# desktop middle click goes on pasting, which is the behaviour this whole
# program exists to get away from - so the desktop's own switch for it is
# program exists to get away from. So the desktop's own switch for it is
# turned off too.
#
# KWin has such a switch, and only for a Wayland session, where the paste is a
@@ -26,7 +26,7 @@ MCA_KWIN_KEY="EnablePrimarySelection"
# The kconfig command line tools, whichever generation this session has. They
# are what System Settings writes kwinrc with, and worth the fork: the file has
# a cascade behind it - /etc/xdg, the kdedefaults directory - and entries a
# a cascade behind it (/etc/xdg, the kdedefaults directory) and entries a
# distribution can mark immutable, and an edit that reaches past all that with
# sed writes something KDE goes on to ignore.
MCA_KDE_TOOL=''
@@ -81,8 +81,8 @@ mca_kde_read() {
local file="${1:-$MCA_KWINRC}" gen val
gen="$(_mca_kde_tool)" || return 1
# kreadconfig creates the file it is pointed at, and the status screen -
# which asks on every redraw - has no business writing anything. A file
# kreadconfig creates the file it is pointed at, and the status screen
# (which asks on every redraw) has no business writing anything. A file
# that is not there has no value in it to read anyway.
[[ -f $file ]] || return 0
@@ -124,7 +124,7 @@ mca_kde_paste_apply() {
if mca_ledger_has "$MCA_KWINRC"; then
# Ours already. What goes back is the value recorded the first time
# round, not what reading the file now would say - that is false, and
# round, not what reading the file now would say. That is false, and
# false is what is being undone.
previous="$(mca_ledger_detail "$MCA_KWINRC")" || previous=unset
elif [[ $current == false ]]; then
+8 -8
View File
@@ -32,7 +32,7 @@ mca_ui_term_restore() {
}
# Runs an action with the terminal handed back to normal line mode, so anything
# it prints - or prompts for - behaves the way a program expects.
# it prints or prompts for behaves the way a program expects.
mca_ui_cooked() {
mca_ui_term_restore
"$@"
@@ -126,8 +126,8 @@ mca_pause() {
# _mca_row <label> <value>
# printf's %-28s pads by bytes, so a label containing "ü" comes out one column
# short. ${#s} counts characters in a UTF-8 locale, so the padding is computed
# here instead - and applied inline, because command substitution would eat the
# trailing spaces again.
# here instead. It is applied inline, because command substitution would eat
# the trailing spaces again.
_mca_row() {
local label="$1" value="$2" pad
pad=$(( 30 - ${#label} ))
@@ -172,7 +172,7 @@ mca_ui_status() {
if (( MCA_N_UNKNOWN )); then
_mca_row "$(mca_msg "Not identified")" \
"${MCA_C_DIM}$(mca_msg "%d - see the applications list" "$MCA_N_UNKNOWN")${MCA_C_RESET}"
"${MCA_C_DIM}$(mca_msg "%d (see the applications list)" "$MCA_N_UNKNOWN")${MCA_C_RESET}"
fi
if mca_steam_installed; then
@@ -294,7 +294,7 @@ mca_ui_settings() {
local title hint
mca_msg_into "$locale" "Settings"; title="$MCA_MSG_RESULT"
mca_msg_into "$locale" "Up/Down select - Space or Right changes - q goes back"
mca_msg_into "$locale" "Up/Down: select, Space or Right: change, q: back"
hint="$MCA_MSG_RESULT"
local clearseq
@@ -387,11 +387,11 @@ mca_ui_apps() {
local title hint legend warn
mca_msg_into "$locale" "Applications"; title="$MCA_MSG_RESULT"
mca_msg_into "$locale" "Up/Down select - Space turns one on or off - q goes back"
mca_msg_into "$locale" "Up/Down: select, Space: turn on or off, q: back"
hint="$MCA_MSG_RESULT"
mca_msg_into "$locale" "Anything not identified is left alone until it is turned on here."
legend="$MCA_MSG_RESULT"
mca_msg_into "$locale" "Autoscroll is off - this is what would be covered."
mca_msg_into "$locale" "Autoscroll is off. This is what would be covered."
warn="$MCA_MSG_RESULT"
# The per-row labels are resolved once, here. Looking them up inside the
@@ -554,7 +554,7 @@ mca_ui_menu() {
fi
;;
q|Q) mca_ui_term_restore; trap - EXIT INT TERM; return 0 ;;
# Anything else - Enter, arrow keys, stray characters - just
# Anything else (Enter, arrow keys, stray characters) just
# redraws. Escape is deliberately not a quit key, so a mistyped
# arrow key cannot close the menu.
*) ;;
+16 -16
View File
@@ -4,19 +4,19 @@
#
# There are two ways in, and the order matters:
#
# 1. A flag file. Where the distribution wraps Electron and Chromium in a
# 1. A flag file. Some distributions wrap Electron and Chromium in a
# launcher script that reads extra arguments from
# $XDG_CONFIG_HOME/<name>-flags.conf - Arch and its derivatives do, and it
# is the convention their packages follow - this is the good one: it is
# the supported way to pass arguments, it survives package upgrades
# $XDG_CONFIG_HOME/<name>-flags.conf. Arch and its derivatives do, and
# their packages follow that convention. Where it exists, this is the good
# way in: it is the supported way to pass arguments, it survives package upgrades
# untouched, and it applies however the program is started, including from
# a terminal.
#
# Nothing is assumed about which distribution this is. The launcher itself
# is read, and the route is taken only for a launcher that really does
# name such a file. Elsewhere - Debian, Ubuntu, Fedora, openSUSE, where
# the equivalent file lives under /etc and is the system's to write -
# there is no flag file to use and route 2 answers for everything.
# name such a file. On Debian, Ubuntu, Fedora and openSUSE the
# equivalent file lives under /etc and is the system's to write. There is
# no flag file to use there, and route 2 answers for everything.
#
# 2. A desktop entry. For applications that ship their own binary with no
# wrapper, and for everything a Flatpak or a snap contains, there is
@@ -176,8 +176,8 @@ mca_flags_apply() {
done
[[ -n $existing_target ]] && return 0
# None exists yet. The last candidate is the wrapper's own fallback - the
# generic electron-flags.conf rather than electron43-flags.conf - so
# None exists yet. The last candidate is the wrapper's own fallback (the
# generic electron-flags.conf rather than electron43-flags.conf). So
# creating that one also covers every other application using the same
# shared Electron.
target="${candidates[-1]}"
@@ -319,7 +319,7 @@ MCA_MARK_SHADOW='X-MCA-Generated'
MCA_MARK_INPLACE='X-MCA-Patched'
# _mca_desktop_transform <file> <marker> [flags] [position]
# The whole file with every Exec line rewritten - the main one and the one in
# The whole file with every Exec line rewritten: the main one and the one in
# each Desktop Action, because those are the right-click menu entries and a
# user who starts Steam from "Library" expects the same behaviour there.
_mca_desktop_transform() {
@@ -360,8 +360,8 @@ mca_desktop_apply() {
local target="$MCA_APPDIR/$id.desktop" content backup
if [[ "$src" == "$target" ]]; then
# The user's own entry - an AppImage, a web app shortcut, something
# installed by hand. There is nowhere to shadow it from, so it is
# The user's own entry, like an AppImage, a web app shortcut or
# something installed by hand. There is nowhere to shadow it from, so it is
# edited directly and the original is kept.
grep -q "^$MCA_MARK_INPLACE=" "$src" 2>/dev/null && return 0
@@ -383,7 +383,7 @@ mca_desktop_apply() {
mkdir -p "$MCA_APPDIR" 2>/dev/null || return 1
# Something is already shadowing this entry. Unless it is a shadow of ours,
# it is the user's own file - possibly one we edited in place earlier - and
# it is the user's own file (possibly one we edited in place earlier), and
# overwriting it here would lose it.
if [[ -e $target ]] && ! grep -q "^$MCA_MARK_SHADOW=" "$target" 2>/dev/null; then
return 1
@@ -407,8 +407,8 @@ mca_desktop_apply() {
# entry in the menu completely, which is why Discord launched at login used
# to behave differently from Discord launched from the menu.
#
# The desktop folder, where a shortcut somebody dragged out of the menu -
# or asked Steam for - lives and nowhere else.
# The desktop folder, where a shortcut somebody dragged out of the menu
# (or asked Steam for) lives and nowhere else.
#
# Neither can be shadowed from anywhere, so both are edited where they stand,
# with the original kept.
@@ -568,7 +568,7 @@ mca_spotify_apply() {
# Uninstalling something deletes its entry from /usr/share/applications, but the
# copy shadowing it is in the user's home and pacman knows nothing about it. It
# would sit in the menu forever, offering to start a program that is no longer
# installed - and the watcher would not notice, because a plain apply only ever
# installed. And the watcher would not notice, because a plain apply only ever
# looks at what is there now. A file that was edited where it stood and has
# since been deleted is the same problem from the other side: its record would
# have `disable` put the file back.
+11 -11
View File
@@ -2,25 +2,25 @@
#
# Steam.
#
# Steam's interface is CEF, so the feature is there - but Steam builds the
# Steam's interface is CEF, so the feature is there. But Steam builds the
# command line for its web helper itself and offers no way to add to it. The
# only place to get an argument in is the shell script that starts the helper,
# which lives inside Steam's own installation:
#
# ~/.local/share/Steam/ubuntu12_64/steamwebhelper_sniper_wrap.sh
#
# Steam compares the installed files against its manifest at every start - by
# size and timestamp rather than by content - and restores whatever differs.
# Steam compares the installed files against its manifest at every start (by
# size and timestamp, not by content) and restores whatever differs.
# So the patch is written to look untouched: the bytes the flag costs are taken
# back out of the script's comments and the timestamp is put back afterwards,
# which leaves a file that is byte-for-byte the size Steam recorded and as old
# as Steam left it. A client that verifies its files finds nothing to repair
# and the flag survives however Steam was started - from the menu, from a game
# shortcut, from a launcher like Heroic, from a terminal.
# and the flag survives however Steam was started: from the menu, from a game
# shortcut, from a launcher like Heroic, or from a terminal.
#
# A patch that changes the length is not an option, and no switch covers for
# one. Steam checks its files at a start it was given arguments for, but also
# at the shutdown it runs itself - and that one has no -noverifyfiles on its
# at the shutdown it runs itself. That one has no -noverifyfiles on its
# command line, whatever the session was started with. What a single wrong
# length costs is the whole client package downloaded, extracted and installed
# again, and a client that quits at the end of it instead of coming up. So the
@@ -114,8 +114,8 @@ _mca_steam_exec_line() {
# The patched script on stdout: the flags appended to the line that starts the
# web helper, and the same number of bytes taken back out of the script's
# comments, so that the file Steam finds is the length Steam wrote down.
# Everything else - setting up the container runtime, deciding whether the
# sandbox can be used - is left alone.
# Everything else is left alone, like setting up the container runtime or
# deciding whether the sandbox can be used.
#
# Comments are eaten from the bottom up, so the header that says what the
# script is for is the last thing to lose anything, and the '#' itself always
@@ -180,8 +180,8 @@ _mca_steam_refresh_backup() {
# The script is already patched. Whether that is a patch Steam can live with is
# a question of length: an earlier version of this program appended the flag
# where the comments could not pay for it, which leaves the script longer than
# the file Steam wrote down - and a client that checks its files reinstalls
# itself over that, then quits instead of starting.
# the file Steam wrote down. A client that checks its files reinstalls itself
# over that, then quits instead of starting.
#
# Rebuilt from the untouched original kept when the script was first patched,
# never from the patched file, the flag either fits this time or the original
@@ -277,7 +277,7 @@ mca_steam_revert() {
return 0
fi
# No backup to fall back on - take the flags back out of the exec line.
# No backup to fall back on, so take the flags back out of the exec line.
[[ -f $script ]] || return 1
local tmp
tmp="$(mktemp "${script}.XXXXXX")" || return 1
+3 -3
View File
@@ -1,11 +1,11 @@
#!/usr/bin/env bash
#
# middleclick-autoscroll - middle-click autoscroll for Chromium-based
# 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
# 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.
@@ -50,7 +50,7 @@ mca_do_enable() {
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 - newly installed applications will not be picked up on their own.")"
mca_note "$(mca_msg "No systemd user session, so newly installed applications will not be picked up on their own.")"
fi
fi