Skip to content
Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time




Some time ago I posted on reddit, saying that the i3 window manager was very well suited to my needs as someone living with Parkinson’s Disease, a condition that arises when dopamine producing neurons in the brain start dying. You are currently reading the README for the github repository dopamine, that I’m using and actively working on. I chose the name dopamine to be short and memorable. I made a follow-up post on reddit about the dopamine project and there was once again an ongoing discussion. Dopamine is as much about evaluating what doesn’t work as it is about what works!

How to run dopamine

I’d like to know if anyone tries or wants to try, but it’s a mess. I’ll help you if you ask on reddit. Consider evaluating dopamine on a VirtualBox VM because (1) you minimise the risk of breaking your current install, and because (2) dopamine is running on Xubuntu 16.04/18.04 LTS]. See for an easy and safe way to install i3 on Xubuntu (i3 replaces the XFCE window manager).


i3files directory

The i3files directory contains my i3 configuration files and some i3-related helper scripts. The other directories contain configurations and scripts that I use in conjunction with the aforementioned i3 files. These other files provide context for i3 and my PD; on github they act as my backups. The i3files are discussed in depth in a later section.

i3-make script

i3-make is a script that calls 'make' on the Makefile in the 'i3files' working directory. I have it bound to Control-Menu. Running i3-make will run ShellCheck on any script in the working directory that differs from its counterpart scripts in the installation directory, if ShellCheck is happy, the modified script is installed. The i3 config file and the i3status file are installed if i3 is happy; i3 config is reloaded and i3 is restarted as necessary. If ShellCheck objects to a bad script, look at 'i3files/*.log' for the errors and suggestions to fix them.

The example below shows how to configure Makefile variables (for my machine) by editing i3-make instead of editing the Makefile.

# i3-make

I3FILES=$(readlink -f ${HOME}/1/EllaTheCat/github/dopamine/i3files)
cd ${I3FILES}
make \
    CONFIGURED=true I3BIN="${HOME}/local/bin" \
    -f ${I3FILES}/Makefile -C ${I3FILES} "$@"

dotfiles directory

My PD makes dot-inputrc absolutely essential; combined with a huge bash history size set by dot-bashrc, I can recall, edit and apply commands with minimal typing. I type a few letters to filter what is to be shown, then use up arrow or down arrow to cycle through matching commands. The dot-bashrc has some nice github functions and a prompt that knows about git.

The files here are the ones I use. Nothing here is installed by the Makefile in i3files.

dotemacs directory

Emacs and dopamine provide a minimalist voice-assisted editing feature. Spoken sentences are converted to text externally about which more later. The text is inserted into an Emacs buffer as a single line by default.

The files here are the ones I use. Nothing here is installed by the Makefile in i3files.

scripts directory

These are scripts have come in handy, for example when making a video.

The files here are the ones I use. Nothing here is installed by the Makefile in i3files.



At first I thought modes would completely replace modifiers in my way of working. I’ve realised that there are some i3 commands that don’t suit modes, but modifiers don’t suit me. The compromise is to use the numeric keypad, alias the numpad, as found on the far right of full-size keyboards. Separate USB numpads are an option for on-the-move laptop users and left handed users.

The NumLock key toggles between two sets of keys: the KP_0 set for numeric entry and the KP_Insert set for navigation. The arithmetic operators and KP_Enter are unaffected by NumLock.

Take a look at "i3files/dot-config-i3-config" for the bindings.

i3 modes

There are now only three major i3 modes: the default mode, the Primary mode, and the Secondary mode. The Menu key cycles through these modes, the space key returns to default mode from the other two. The screen dims when in Primary or Secondary mode.

  • Primary mode contains my most often used bindings after the numpad ones.

  • Secondary mode contains bindings to less-used functions such as settings.


Commands are a hangover from a past attempt to make a mouse-heavy window manager keyboard-operable. The concept was to either launch a program or switch to a running instance.

Press Menu followed by Tab to show a dmenu with a "Command:" prompt. There is just enough time to enter two or three characters before the dmenu is automatically dismissed. Whatever has been entered is evaluated as a command. Pressing backslash instead of Tab is an alternative binding on my 105 key keyboard.

Pressing KP_Insert shows the same dmenu with its "Command:" prompt The numpad reconfigures to supply the numbers on keys KP_0 KP_1 …​ KP_8 KP_9. Entering 2 or 3 digit commands is facilitated, even with my right hand tremor, probably due to the compact arrangement of the numpad.

Commands themselves are explained in more detail in subsection "Launch or Focus" in section "i3-wrapper".

Numeric Commands

I have only recently found a reliable method of saying two or three digit numbers that returns consistently formatted values. To issue the command "42", say "42 dollars", Google returns "$42", strip the dollar sign, apply a leading zero for values less than 10, and we have a two digit number. Previously results could be mixed format (one,1) or homophones (for/four/4).

Hybrid Commands

These are the ten Emacs frame (window) commands e[0-9], and the ten Google Chrome commands g[0-9]. They are discussed in more detail in the section "Launch or Focus".


Whenever a terminal, emacs frame, or google chrome window is created, a unique two digit mark is allocated and displayed on the right side of the titlebar. The quick-and-dirty implementation of mark assignment risks failing to terminate when the number of marked containers approaches 100. I am contemplating allocating marks for (almost) everything.

i3 has a goto-mark function bound to the 2 digit sequence [0-9][0-9] and a swap-container-with-mark function bound to the 3 digit sequence 5[0-9][0-9]. Exchanging marks can make rearranging windows easier than relying upon the conventional incremental movement of focus or windows alone.

Bash scripts


This script is the main one and is described in detail in the section after this one. The other scripts described in this section are the result of refactoring i3-wrapper. The refactoring is still work in progress.


I’m from the UK, but I prefer the US keyboard layout because back in the day there was no choice but the US layout. I have a 105 key UK keyboard, and this script creates my custom US-style keyboard.

Apropos of i3, this is where I invoke xcape to define how modifier keys work when pressed singly.

  • k1='Super_L=Menu'

  • k2='Alt_L=Escape'

  • k3='ISO_Level3_Shift=Escape'


A recent useful idea from reddit is "mouse follows focus": When the keyboard is used to focus a window, the mouse is warped into the window, to a point offset from the top left corner by one-third of the window width and one-third of the window height. Using the mouse to focus a window with a single click highlights the region between the mouse click point and the keyboard focus point. Using a slow double-click instead leaves no highlight.


I simply don’t like automatic display blanking, but because my tremor would easily disturb the mouse I can’t allow automatic display unblanking. Keybindings can use this script request that the display sleeps or wakes up.

I have two monitors driven from my PC, and I hope to have three again in future. The left monitor can be driven from other sources, Fire Stick, NowTV STB, Raspberry Pi, …​ I wish to avoid selecting inputs with buttons on the left monitor. Keybindings can use this script to send commands to both sources such that the left monitor source can be selected programmatically.

This works, but has been seldom used because my monitors have been configured to disable automatic HDMI switching. It does no harm at present so there is no reason to remove it.


This script is a straightforward wrapper round 'i3status'. It adds several things:

  • Status of a firewall rule

  • On/Off control and status for USB audio dongle microphone, USB webcam microphone and analog stereo microphone.

  • Webcam device file owner (lsof).

  • A list of the marks that are assigned to terminals, Emacs frames, Chrome windows, and certain other windows.


This script makes explicit how the applications I use should be started and stopped.


File Watcher

The file watcher monitors a file in shared memory, using inotify-hookable. When a command is written to this file, it is forwarded to the i3programs() function in i3-wrapper for evaluation.

As of 2020-01-28 there is a bug. Commands are ignored, the onset occurs soon after the session starts, it occurs once only, and the workaround is to type control-C in the File Watcher window, after which the ignore commands are executed.

Launch or Focus

The focus function in i3-wrapper has a bash case statement that accepts commands to launch or focus a program using the aforementioned focus function:

  • If a requested program is not already running, the focus function will launch the requested program in a designated workspace on a designated output.

  • If a requested program is already running, the focus function changes to its workspace and to its output.

The example here launches thunderbird in response to command "tb", launching on the workspace "tb" on the left monitor ${lmon}, unless a Thunderbird window exists, in which case ithe window will receive focus on whatever workspace or output it currently occupies.

focus class Thunderbird 'tb' ${lmon} thunderbird ;;

Not all case statements use the focus function. The ten 'g0 g1 …​ g8 g9' commands launch or focus Google Chrome windows on eponymous workspaces. The "gc" command will launch a Google Chrome window on the current workspace. There are also ten commands 'e0 e1 …​ e8 e9' that launch or focus Emacs frames on eponymous workspaces, and 'em' for the current workspace. These all rely on the 'emgc' function instead of 'focus'. Their names are the "standard" names that other features may expect, as does the focus watcher for example.

Scratchpad Terminal

The popularity of dropdown terminals (Guake, Yakuake …​) has seen i3 users implementing similar functionality using the i3 scratchpad.

A single key binding (Control+Delete) operates the scratchpad terminal. The first two presses perform initialisation, subsequent presses toggle the scratchpad terminal between being visible and being hidden;. There is no dropdown animation. I have locked the terminal to a fixed position on my primary monitor.

My decision to use Control+Delete despite my right hand tremors relies on the space between the two key clusters to the left of the numpad to rest my fingers and steady my hand.


My external speech to text engine uses the Android apps Tasker and AutoVoice. Tasker writes a sentence or command into the file monitored by the file watcher.

My frontend for speeech to text is the AutoVoice for Chrome extension. It provides continuous listening without hotphrases such as "OK Google" or "Alexa". This requires streaming audio out of the machine at roughly 128 kbps, so be careful if your broadband is metered, or if you wish to keep secrets.

The i3-tasker function i3-autovoice uses xdotool to toggle AutoVoice on/off on the extension’s webpage "chrome://extensions/?id=…​" (not the Options page) as of Chrome Version 77.0.3865.90 (Official Build) (64-bit). I hope it stays available. This is the better choice to serve as an on/off switch provided that the user accepts the implementation (c.f. the Tasker plugin AutoInput).

Muting the microphone input to the AutoVoice for Chrome extension reduces the upstream bandwidth significantly and serves as an alternative and effective on/off switch.




Linux PC i3 window manager configuration specific to my having Parkinson's Disease



No releases published


No packages published