Fix Palemoon browser mouse scroll wheel goes through history when using Fluxbox

The solution

In my ~/.fluxbox/startup:

xinput set-button-map "$( xinput | awk -F'[=]' '/ouse/{print $2}' | awk '{print $1}' | head -n1 )" 1 2 3 4 5 6 7 0 0 &

The story

I installed Devuan ceres on a desktop workstation as part of my research into lightweight window managers. I installed my self-rolled dpkg of Palemoon (source on gitlab) because I have been actively reducing my use of upstream Firefox. When I scrolled up with the mouse wheel, the browser jumped back and forth in history. If the current tab in the browser has no previous pages, then the scrolling operates just fine.

Apparently I’m a unicorn. Nobody has had this exact problem in this environment before (Windows users of Firefox changing the about:config don’t count). Relevant xkcds include a tiny bit of xkcd#979 and a healthy dose of xkcd#1495.

I investigated many different methods to try to solve my problem. I tried changing the about:config settings in the browser (specifically mousewheel.default.action and similar) which did not solve my problem.

My next attempt involved file ~/.fluxbox/keys to assign commands to mouse button actions to reduce the effect they have in the window, which failed to suppress the undesirable actions.

I investigated using xbindkeys to control what is sent to the X server when it receives certain inputs. I even tried complicated guile logic, which actually seems quite nifty, but it just didn’t accomplish what I wanted in this case. I found an interesting example (secondary reference 3) where some toggling logic was shared, and I spent a lot of time trying to tinker with that.

I finally found what I was looking for on the Arch Wiki (primary reference 1), go figure. Those Arch folks know how to help a guy no matter the distro! You can use xinput to change what signals are sent to X from the device by remapping the buttons. You can suppress a button with 0.
The wiki helpfully explains how to find which device to modify. And then the series of numbers after that are the button mappings. So the first button, is mapped to the first number, and so on. If a button is mapped to 0, it is effectively ignored.

xinput set-button-map "$( xinput | awk -F'[=]' '/ouse/{print $2}' | awk '{print $1}' | head -n1 )" 1 2 3 4 5 6 7 0 0 &

In my example, I mask buttons 8 and 9. Using xev and xbindkeys -mk I learned that my mouse (a generic HP mouse since I’ve never cared about fancy peripherals) sends button 4 on scrolling up, and then button 8 and button 9 when stopping the scrolling up action. It was the button 8 (and 9) that were causing weird issues with the browser. When I mask the input with xinput as seen here, the scrolling operates completely normally and as expected.

The probable causes

I have been using this mouse with Xfce on Fedora for years, and the scrolling has never been a problem. I suspect my choice of installing all the packages myself on a Devuan netinst contributed to the problem. I had an issue with fonts on xscreensaver which was probably due to my minimal install. Perhaps Fluxbox does not perform some perfunctory task that desktop environments (DEs) do with sanitizing input. I don’t care, because Fluxbox has been quite satisfactory.

And as a side node, I haven’t found a debian-family “minimal” disc that can be used independently of a network, like the CentOS minimal disc image, only a netinst.



  1. Mouse buttons – ArchWiki []


  1. XBindKeys []
  2. xbindkeysrc.scm []
  3. [SOLVED] [xbindkeys] Advanced mouse binds? []
  4. fluxbox-keys(5) Manual Page []


xev – uesful to display info about keys are being pressed

xbindkeys -mk – same

xinput – manipulate mouse button mapping






Expect use environment variable if defined

Here is how to use a variable

set a FOOBAR
puts "the contents of a is $a"

Here is how to use an environment variable in expect/tcl.

puts "env var MYVAR is $env(MYVAR)"

Here is what happens when you try to use an environment variable if it is undefined.

$ ./mine.exp
no such variable
    (read trace on "env(MYVAR)")
    invoked from within
"puts "$env(MYVAR)""
    (file "./" line 2)

Here is how to use a fallback value if the environment variable fails.

set MYVAR defaultvalue
catch {set MYVAR $env(PREFERRED_VALUE)}
puts "$MYVAR"



  1. How to access environment variables in an Expect script? – Stack Overflow



Some useful Fluxbox configurations

I am investigating using a lightweight window manager instead of a whole desktop environment. I know how to manually mount external disks, and control files on the command line, so why bother with the overhead of a whole DE when I could just get by with a mere wm?

Fluxbox was my first window manager experiment. I already love it. Everything about it spartan. I love spartan.

Fluxbox is not terribly xdg compliant, which is something to note but is not really a problem. I haven’t found a devuan equivalent of xdg-menu [Arch wiki] yet, so for now I’ll just hit Alt-F2 and run applications by binary name.

My ~/.fluxbox/startup file includes these lines so far:

# BEGIN apps in startup file
spice-vdagent &
volumeicon &
copyq &
teamviewer &

And my ~/.fluxbox/keys file has some carefully gleaned additions.

Control Shift z :ExecCommand copyq menu

# replace the shade behavior for double mouse click on titlebar
OnTitlebar Double Mouse1 :Maximize

# window tiling like Cinnamon
# half-screen
# adapted from
#       Up 111
# Left 113    Right 114
#     Down 116
Mod4 111 :MacroCmd {ResizeTo 100% 50%} {MoveTo 00 00 Up}
Mod4 113 :MacroCmd {ResizeTo 50% 100%} {MoveTo 00 00 Left}
Mod4 114 :MacroCmd {ResizeTo 50% 100%} {MoveTo 00 00 Right}
Mod4 116 :MacroCmd {ResizeTo 100% 50%} {MoveTo 00 00 Bottom}

# quarter-screen
Mod4 Mod1 111 :MacroCmd {ResizeTo 50% 50%} {MoveTo 50% 00% Up}
Mod4 Mod1 113 :MacroCmd {ResizeTo 50% 50%} {MoveTo 00% 00% Up}
Mod4 Mod1 114 :MacroCmd {ResizeTo 50% 50%} {MoveTo 50% 50% Up}
Mod4 Mod1 116 :MacroCmd {ResizeTo 50% 50%} {MoveTo 00% 50% Up}
Mod4 Return :ToggleCmd {Maximize} {Restore}

# move to next monitor
Mod4 Shift 113 :ExecCommand move-to-next-monitor --reverse
Mod4 Shift 114 :ExecCommand move-to-next-monitor 

The move-to-next-monitor project does not yet have a dpkg debian/ build instructions as of the time of this writing, but check my stackrpms repo to see if it does by the time you’re reading this.



  1. Incredible window tiling keybindings Native Window Snapping / Window Tiling with Fluxbox, Openbox, and xfwm4 (Xfce) | Aaditya’s Blog

Install 32-bit chroot on 64-bit devuan for compiling i386 packages

By accident, I installed 32-bit devuan instead of 64-bit, so all my self-hosted dpkgs didn’t work because they are for x86_64 architecture. So I started trying to compile the dpkgs in the new environment, and one in particular (palemoon) would always exhaust memory.

I found a wonderful reference [1] that explains how to set up a 32-bit chroot on 64-bit debian-based GNU/Linux. I tested my adaptation of the instructions on devuan ceres x86_64.

Install schroot and debootstrap.

sudo apt-get install schroot debootstrap

Set up schroot.

touch "${tf}" ; chmod 0644 "${tf}"
cat <<EOF >"${tf}"
description=Devuan ceres 32-bit

Install the new distribution.

mkdir /32
debootstrap --arch i386 ceres /32

Now the chroot is minimally viable, but there are a few recommended steps to take before using it.
Symlink in the mtab.

ln -s /proc/mounts /32/etc/mtab

Copy in any system-wide setting as desired.

cp -p /etc/apt/apt.conf /32/etc/apt/      # for proxy settings
cp -p /etc/apt/sources.list /32/etc/apt/  # for universe, security, etc
cp -p /etc/environment /32/etc/           # for proxy and locale settings
cp -p /etc/sudoers /32/etc/               # for custom sudo settings

Disable services in the chroot.

touch "${tf}" ; chmod 0755 "${tf}" ; chown root.root "${tf}" ;
cat <<EOF >"${tf}"
## Don't start any service if running in a chroot.
## See /usr/share/doc/sysv-rc/README.policy-rc.d.gz
if [ "$(stat -c %d:%i /)" != "$(stat -c %d:%i /proc/1/root/.)" ]; then
  exit 101

Now load up the chroot and prepare a few more packages.

schroot -c ceres32
sudo apt-get update
sudo apt-get install lsb-core

From here, you can install your build dependencies and build i386 dpkgs!



  1. Ripped entirely from How do I run 32-bit programs on a 64-bit Debian/Ubuntu? – Unix & Linux Stack Exchange


Age of Empires 2 on Linux – 2019 Edition

# Installing AoC on Linux without PlayOnLinux

## Variables

export AOCWINEPREFIX=~/.wine
export AOCDIR="${AOCWINEPREFIX}"/drive_c/Program\ Files/Microsoft\ Games/Age\ of\ Empires\ II
export voobly_desktop=~/.local/share/applications/Voobly.desktop
export aofe_desktop=~/.local/share/applications/TheForgottenEmpires.desktop
export aoc_desktop=~/.local/share/applications/TheConquerors.desktop
mkdir -p "$( dirname "${voobly_desktop}" )"

# Learn OS and flavor
. /usr/share/bgscripts/

# Install wine-staging
# References:
case "${thisflavor}" in
      sudo su -
      #wget -nc
      dpkg --add-architecture i386 # needed for packages
      wget -nc
      apt-key add Release.key && /bin/rm -f Release.key
         echo "# And for Debian Sid this one:"
         echo "deb sid main"
      } >> /etc/apt/sources.list.d/winehq.list
      apt-get update
      apt-get install -y winehq-staging winetricks
      test "${USER}" = "root" && exit

      # Fedora already has wine staging
      sudo dnf -y install wine.i686 winetricks

export WINEARCH=win32

winetricks -q directplay

# mount AoE2 disc
sudo mkdir -p /mnt/aoe2
sudo mount -v -o loop /mnt/public/CDROMs/Games/AgeOfEmpires/ISO/AOE2.ISO /mnt/aoe2

# install AoE2
wine /mnt/aoe2/AOESETUP.EXE

# mount AoC disc
sudo mkdir -p /mnt/age2_x1
sudo mount -v -o loop /mnt/public/CDROMs/Games/AgeOfEmpires/ISO/AGE2_X1.ISO /mnt/age2_x1

# install AoC
wine /mnt/age2_x1/AOCSETUP.EXE

sudo umount -lv /mnt/age2_x1 ; sudo umount -lv /mnt/aoe2 ; sudo rmdir /mnt/aoe2 /mnt/age2_x1

# Install aoc 1.0c
cp -p /mnt/public/Support/Setups/Games/Age2XPatch.exe "${AOCDIR}"
wine "${AOCDIR}"/Age2XPatch.exe

# Install AoFE
# If the download is working.
#cp -p '/mnt/public/Age Of Empires/Downloaded/AoFE_Launcher.exe' "${AOCDIR}"
#pushd "${AOCDIR}"; wine "${AOCDIR}"/AoFE_Launcher.exe ; popd
# Alternate instruction for getting AoFE
pushd "${AOCDIR}" ; unzip '/mnt/public/Age Of Empires/Downloaded/' ; mv Age2_x1/* age2_x1/ && rmdir Age2_x1 ; popd

# Install voobly
cp -p /mnt/public/Age\ Of\ Empires/Downloaded/voobly-v2.2.4.51.exe "${AOCDIR}"
wine "${AOCDIR}"/voobly-v2.2.4.51.exe

# get WololoKingdoms, as of 2018-09-22
# which I generated on my one Windows machine with the tool from and the Steam version of the game.
wk_dir="${AOCDIR}/Voobly Mods/AOC/Data Mods"
mkdir -p "${wk_dir}"
pushd "${wk_dir}" ; time 7za x /mnt/public/Age\ Of\ Empires/Wololo\ Kingdoms/ ; popd

# customize voobly desktop file
touch "${tf}"; chmod 0755 "${tf}"
cat < "${tf}"
env WINEPREFIX="${WINEPREFIX}" STAGING_WRITECOPY=1 /usr/bin/wine C:\\\\Program\\ Files\\\\Voobly\\\\voobly.exe

mkdir -p ~/.local/share/icons
cp -p '/mnt/public/Age Of Empires/Images/voobly.png' ~/.local/share/icons/
touch "${voobly_desktop}"; chmod 0755 "${voobly_desktop}"
cat < "${voobly_desktop}"
[Desktop Entry]
Path=${WINEPREFIX}/dosdevices/c:/Program Files/Voobly
Comment=Matchmaking service for AoC

# customize AoFE desktop file
cp -p '/mnt/public/Age Of Empires/Images/age2_x2.png' ~/.local/share/icons/
touch "${aofe_desktop}"; chmod 0755 "${aofe_desktop}"
cat < "${aofe_desktop}"
[Desktop Entry]
Name=The Forgotten Empires
Exec=env WINEPREFIX="${WINEPREFIX}" /usr/bin/wine "${AOCDIR}/age2_x1/age2_x2.exe" /nostartup
Comment=Forgotten Empires 2.2 mod for AoC

# customize AoC desktop file
thisicon="$( find ~ -regex '.*.local.*age2_x1.*png' 2>/dev/null | sort | tail -n1 )"
touch "${aoc_desktop}"; chmod 0755 "${aoc_desktop}"
cat < "${aoc_desktop}"
[Desktop Entry]
Name=The Conquerors
Exec=env WINEPREFIX="${WINEPREFIX}" /usr/bin/wine "${AOCDIR}/age2_x1/age2_x1.exe" /nostartup
Comment=Age of Empires 2: The Conquerors Expansion

echo done

Firefox disable recommended extensions

Firefox apparently is trying to jump the shark with even more pocket-esque behavior. This is why I install Pale Moon (and its Linux page) on my new builds instead of Firefox.

I normally schedule my posts, in case you couldn’t tell, for the morning of every fourth day. But this post is going out immediately.

Disable Firefox’s “Contextual Feature Recommender” with this entry in prefs.js:

user_pref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr", false);

You can extrapolate the about:config option.

Other places on the Internet show you how to do it through the gui if you prefer.


My own research (diff prefs.js prefs.js.old)

List files in dpkg that is not installed

Ripped directly from dpkg – How do I get a list of installed files from a package? – Ask Ubuntu
To see all the files the package installed onto your system, do this:

dpkg-query -L

To see the files a .deb file will install

dpkg-deb -c

To see the files contained in a package NOT installed, do this once (if you haven’t installed apt-file already:

sudo apt-get install apt-file
sudo apt-file update


apt-file list

xorg show current config

If you already have X running, and you try to generathe the xorg.conf file, you might get an error.

$ sudo Xorg -configure 
Fatal server error:
(EE) Server is already active for display 0
        If this server is no longer running, remove /tmp/.X0-lock
        and start again.
Please consult the The X.Org Foundation support 
 for help. 

What you need to do is use another virtual display/terminal/whatever (I’m still learning these terms).

sudo X :2 -configure

Thanks to Joe-ubunt at the Ubuntu Forums: [SOLVED] generate xorg.conf from current configuration

FreeFileSync 10.9 on CentOS 7

Now, you can go install FreeFileSync 10.9 on CentOS 7 from an rpm built on CentOS 7! The upstream release follows some newer versions of libs (clearly compiled on a different platform than CentOS or even Fedora), and I have now compiled those versions based on the work of a genius fellow over at city-fan.

To get FreeFileSync on CentOS 7, you need to load up two of my coprs as seen in the following table.

COPR name repo file
bgstack15/stackrpms bgstack15-stackrpms-epel-7.repo
bgstack15/FreeFileSync bgstack15-FreeFileSync-epel-7.repo

The application depends on some newer libs, which are all available in a second copr.

 Package                   Arch   Version                Repository              Size
 freefilesync              x86_64 10.9-2.el7             bgstack15-stackrpms    3.2 M
Installing for dependencies:
 libpsl                    x86_64 0.7.0-1.el7            bgstack15-FreeFileSync  45 k
 openssl-freefilesync-libs x86_64 1:1.1.0h-3.stack.el7   bgstack15-FreeFileSync 1.2 M
Updating for dependencies:
 curl                      x86_64    bgstack15-FreeFileSync 557 k
 libcurl                   x86_64    bgstack15-FreeFileSync 502 k
 libssh2                   x86_64 1.8.0-10.0.stack.rhel7 bgstack15-FreeFileSync 103 k

Transaction Summary
Install  1 Package  (+2 Dependent packages)
Upgrade             ( 3 Dependent packages)

Total download size: 5.6 M
Is this ok [y/d/N]: 

The artifacts used to produce this build are in my gitlab.