301 lines
13 KiB
Scdoc
301 lines
13 KiB
Scdoc
middleclick-autoscroll(1)
|
|
|
|
# NAME
|
|
|
|
middleclick-autoscroll - middle-click autoscroll in every application that supports it
|
|
|
|
# SYNOPSIS
|
|
|
|
*middleclick-autoscroll* [_command_]
|
|
|
|
# DESCRIPTION
|
|
|
|
Blink, the engine inside Chromium, Electron and CEF, implements Windows-style
|
|
autoscroll: hold the middle mouse button and the page scrolls with the pointer.
|
|
On Linux it is switched off, because middle click is taken by primary-selection
|
|
paste. It can be turned back on with *--enable-blink-features=MiddleClickAutoscroll*
|
|
on the command line.
|
|
|
|
*middleclick-autoscroll* finds every Chromium-based application on the system
|
|
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, 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 of the routes below an application takes is read off its launcher, not
|
|
assumed from where the launcher came from.
|
|
|
|
Run without a command it shows an interactive menu. Everything it can be told
|
|
is reachable from there; the configuration file behind it does not need to be
|
|
edited by hand. Its applications list turns single applications on or off,
|
|
Steam and Spotify included. Its settings hold the rest: the desktop's
|
|
middle-click paste, the watcher, and more Chromium arguments for every
|
|
application.
|
|
|
|
Nothing outside the user's home directory is written to, and running it as root
|
|
is refused.
|
|
|
|
# COMMANDS
|
|
|
|
*enable*
|
|
Turn autoscroll on, apply it to everything installed, and start watching
|
|
for new applications.
|
|
|
|
*disable*
|
|
Turn it off and put every file that was changed back the way it was.
|
|
|
|
*apply* [*--rebuild*]
|
|
Apply to anything that has appeared since the last run. This is what the
|
|
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
|
|
the package manager that removed the application cannot see it.
|
|
|
|
With *--rebuild* everything is taken back first and written again from
|
|
scratch. That is the repair: it does not care what looks correct already.
|
|
|
|
*status*
|
|
How many applications are covered, whether Steam is patched, and when the
|
|
last run was.
|
|
|
|
*list*
|
|
Every Chromium-based application that was found, and how each one is
|
|
handled.
|
|
|
|
*-h*, *--help*
|
|
Show a summary of the commands.
|
|
|
|
*-V*, *--version*
|
|
Show the version.
|
|
|
|
# HOW THE ARGUMENT GETS IN
|
|
|
|
Two ways, chosen per application.
|
|
|
|
*Flag file*
|
|
Where the launcher reads extra arguments from
|
|
_$XDG_CONFIG_HOME/<name>-flags.conf_. This is the preferred route: it is
|
|
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
|
|
a second one would switch the first one off.
|
|
|
|
Arch's Electron and Chromium packages all wrap their binaries this way, and
|
|
so do a number of individual vendors' launchers elsewhere. Whether a given
|
|
launcher does is read off the launcher itself, never assumed from the
|
|
distribution: only one that really names such a file takes this route.
|
|
|
|
*Desktop entry*
|
|
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.
|
|
|
|
This is the route everything takes on the distributions whose Chromium
|
|
wrappers keep their equivalent file under _/etc_, where it is the system's
|
|
to write and not the user's: Debian, Ubuntu, Fedora and openSUSE among
|
|
them.
|
|
|
|
A generated entry is marked *X-MCA-Generated* and an entry edited in place
|
|
*X-MCA-Patched*. The two are never confused: the first is deleted when
|
|
undoing, the second is restored from its backup. An entry with neither
|
|
marker belongs to somebody else and is left alone.
|
|
|
|
Programs that start themselves at login write their own entry into
|
|
_~/.config/autostart_ pointing straight at their binary, bypassing the menu
|
|
entry entirely. Those are patched in place as well, unless the application is
|
|
turned off in the applications list.
|
|
|
|
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
|
|
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.
|
|
|
|
# STEAM
|
|
|
|
Steam's interface is CEF and supports the feature, but Steam builds the command
|
|
line for its web helper itself. The only way in is the script that starts the
|
|
helper, inside Steam's own installation:
|
|
|
|
~/.local/share/Steam/ubuntu12_64/steamwebhelper_sniper_wrap.sh
|
|
|
|
The steamrt3 client, a beta for now, has a script of its own:
|
|
|
|
~/.local/share/Steam/steamrt64/steamwebhelper.sh
|
|
|
|
Both are patched where both are there, so switching clients keeps autoscroll.
|
|
|
|
Where that installation is depends on how Steam was installed:
|
|
_~/.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, 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, 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
|
|
it: Steam checks its files at the shutdown it runs itself as well as at a start
|
|
it was given arguments for, and that one carries no arguments of anybody's. One
|
|
wrong length costs the whole client package downloaded, extracted and installed
|
|
again, and a client that quits at the end of it instead of coming up.
|
|
|
|
The steamrt3 script has no comments to pay with. So it is copied aside as
|
|
_steamwebhelper.sh.orig_, and a stub of the same size takes its place. The stub
|
|
runs the copy with the argument added. Steam only checks the files it knows,
|
|
and the copy is not one of them.
|
|
|
|
So where neither fits, or a client update has changed how the helper is
|
|
started, nothing is written and the status screen says Steam is not patched.
|
|
Nothing goes on Steam's launcher entry, its autostart entry or the shortcuts it
|
|
writes for single games either, and Steam goes on repairing its own
|
|
installation.
|
|
|
|
An installation patched by an earlier version, which appended where the
|
|
comments were short, is written again to fit at the next apply, or taken back
|
|
if it cannot be made to.
|
|
|
|
A client update brings a new version of the script. The watcher notices and
|
|
patches it again, and the copy kept for undoing is replaced with the new
|
|
version at the same time, so undoing puts back the script Steam last shipped
|
|
rather than the one from before the update.
|
|
|
|
# SPOTIFY
|
|
|
|
The official client is CEF rather than Electron. Installed through
|
|
*spotify-launcher*, it is started by a program that builds its own command line
|
|
and has a configuration file with a slot for extra arguments; that slot is
|
|
where the flag goes, and the launcher shows up in the applications list like
|
|
any other application. Installed as a plain package, a Flatpak or a snap, it is
|
|
an ordinary desktop entry and needs nothing special.
|
|
|
|
# MIDDLE-CLICK PASTE
|
|
|
|
Inside a Chromium application the argument settles this on its own: with
|
|
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, so the desktop's own switch for it is turned off
|
|
too.
|
|
|
|
KDE has such a switch, and only for a Wayland session, where the paste is a
|
|
protocol the compositor either offers or does not:
|
|
|
|
~/.config/kwinrc, [Wayland], EnablePrimarySelection=false
|
|
|
|
It is written with *kwriteconfig6*, the same tool System Settings uses, because
|
|
kwinrc has a cascade behind it and entries a distribution can mark immutable;
|
|
an edit that reaches past all that writes something KDE goes on to ignore. KWin
|
|
reads the key once, while it starts, so the change is true from the next login
|
|
on rather than straight away.
|
|
|
|
What the key said before is recorded, and *disable* puts that back. A key that
|
|
already said *false* before any of this is left alone and not recorded either,
|
|
so a paste the user switched off themselves is never switched back on.
|
|
|
|
On X11 there is nothing to switch. The primary selection is part of X itself
|
|
and every toolkit reaches for it on its own; no one place can say no. The
|
|
status screen leaves the row out where there is nothing to report.
|
|
|
|
Turn it off under *Settings* to keep the desktop's middle-click paste.
|
|
|
|
# APPIMAGES
|
|
|
|
An AppImage is the AppImage runtime, an ordinary executable, with a squashfs
|
|
image appended to it. The payload is compressed, so none of the files that
|
|
identify Chromium is on disk where it could be found.
|
|
|
|
The names are, though. squashfs keeps the name of everything it holds in one
|
|
table of its own, a few kilobytes of it, and a name is all this question needs -
|
|
so that table is read and decompressed in place. Nothing is unpacked, and the
|
|
image is never run: this can happen from the watcher, and starting a program
|
|
because it was installed is not something a scan gets to do.
|
|
|
|
Two kinds of image are still out of reach. One is packed with *lzo* or *lz4*,
|
|
which squashfs stores as bare blocks that neither tool will read without the
|
|
framing their own file formats add. The other is the original AppImage layout,
|
|
which is an ISO9660 filesystem rather than a squashfs one. Both are listed as
|
|
*cannot tell* and left alone until they are switched on from the applications
|
|
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 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
|
|
entirely, rather than being offered as something that could be switched on. An
|
|
application that is absent from *list* is absent because there is nothing this
|
|
tool could do for it.
|
|
|
|
# FILES
|
|
|
|
_~/.config/middleclick-autoscroll/config_
|
|
Written by the program. Every option in it is reachable from the menu.
|
|
|
|
_~/.local/state/middleclick-autoscroll/ledger_
|
|
One line per change, so *disable* can undo exactly what was done and
|
|
nothing else.
|
|
|
|
_~/.local/state/middleclick-autoscroll/backup/_
|
|
Copies of the files that are edited in place rather than shadowed.
|
|
|
|
_~/.config/kwinrc_
|
|
KDE's own configuration. One key in it, *EnablePrimarySelection*, is
|
|
written when the desktop's middle-click paste is turned off, and put
|
|
back by *disable*.
|
|
|
|
_~/.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. Otherwise an entry
|
|
for a file that has not changed would never be looked at again.
|
|
Safe to delete.
|
|
|
|
# ENVIRONMENT
|
|
|
|
*NO_COLOR*
|
|
Disables colour.
|
|
|
|
# REQUIREMENTS
|
|
|
|
Bash 4.2 or newer and GNU coreutils. The watcher needs a systemd user session;
|
|
without one everything else works and applications installed later are picked
|
|
up at the next *apply* rather than on their own.
|
|
|
|
*gzip* is what reads the name table of an AppImage, and *xz* or *zstd* the ones
|
|
packed with those instead. None of the three is required: an image whose
|
|
compressor has no tool installed is listed as *cannot tell*, exactly like the
|
|
two formats there is no reader for at all.
|
|
|
|
# SEE ALSO
|
|
|
|
*systemctl*(1), *flatpak*(1), *snap*(8), *kwriteconfig6*(1)
|
|
|
|
# AUTHORS
|
|
|
|
Felitendo. Source and issue tracker at
|
|
https://github.com/LoonixTools/middleclick-autoscroll
|