Quick Tip: Fix Scroll Lock

I found on my desktop that the scroll lock key doesn’t work. I’m using Ubuntu 17.04 (recently upgraded from 16.10, on which the problem also existed) with the i3 window manager and using a Logitech K120 keyboard (which seems to have this problem somewhat commonly).

All of the event signals were there, as tested by xev and other tools, but it wouldn’t actually turn on the scroll lock functionality or change the keyboard LED state.

The problem was that the key was not actually bound to that function, which is fixed by this command:

xmodmap -e 'add mod3 = Scroll_Lock'

This can be run in any number of places, including in a regular terminal for testing or temporary use. I put it in my i3 config file to run at startup each time and it works beautifully.


ThinkPad T440s Battery Warning Script for Ubuntu 16.04

Since I started with a stripped-down Ubuntu install that doesn’t include much in the way of power management I made a tool to warn me when my battery is low and to suspend the system when it is low enough. I borrowed some content and structure from this script, adding features to meet my own needs, in particular support for a second battery, notifications, and auto-suspend.

This script assumes you’ve got two batteries and will warn when both batteries are discharging or discharged (status = “unknown”) and both have remaining power below a certain threshold.

It saves status files in ~/tmp as per the TMPDIR variable at the top to keep from notifying you every minute or however often you choose to have this run. Those files are cleared when either of the batteries begins charging.

At 15% remaining a notification is given through the dbus desktop notification system. At 10% another notification is issued and a sound played. At 8% another notification is given, and a 15 second timer started, after which the system is suspended.


#get access to the dbus session for desktop notifications - must be used inconjunction with the other script run at startup to populate this file with that session information
if [ -r "$HOME/.dbus/Xdbus" ]; then
    . "$HOME/.dbus/Xdbus"


STAT1=$(cat "$DIR1/status")
STAT2=$(cat "$DIR2/status")

echo "Battery1: $STAT1"
echo "Battery2: $STAT2"

#if both batteries are either discharging or discharged (status unknown)
if [ \( "$STAT1" = "Discharging" -o "$STAT1" = "Unknown" \) -a \( "$STAT2" = "Discharging" -o "$STAT2" = "Unknown" \) ];
        REM1=$(cat "$DIR1/energy_now")
        REM2=$(cat "$DIR2/energy_now")
        FULL1=$(cat "$DIR1/energy_full")
        FULL2=$(cat "$DIR2/energy_full")
        PRCT1=$((100 * $REM1 / $FULL1))
        PRCT2=$((100 * $REM2 / $FULL2))

        echo "Power - Battery1: $PRCT1%, Battery2: $PRCT2%"

        if [ $PRCT1 -le 8 ] && [ $PRCT2 -le 8 ];
                notify-send "Battery Critical" "Suspending while there's a little juice left. You have 15 seconds."
                #you will not hear this if the sound is muted - assuming if the sound is muted it should stay that way.
                paplay /usr/share/sounds/freedesktop/stereo/suspend-error.oga
                sleep 15
                sudo systemctl suspend
        elif [ $PRCT1 -le 10 ] && [ $PRCT2 -le 10 ];
                if [ ! -f $TMPDIR/battwarn10 ];
                        notify-send "Battery Low" "Remaining battery is at 10% or lower"
                        #you will not hear this if the sound is muted - assuming if the sound is muted it should stay that way.
                        paplay /usr/share/sounds/freedesktop/stereo/suspend-error.oga
                        touch $TMPDIR/battwarn10
        elif [ $PRCT1 -le 15 ] && [ $PRCT2 -le 15 ];
                if [ ! -f $TMPDIR/battwarn15 ];
                        notify-send "Battery Low" "Remaining battery is at 15% or lower"
                        touch $TMPDIR/battwarn15
elif [ "$STAT1" = "Charging" ] || [ "$STAT2" = "Charging" ];
        #if the status is charging, clear the temp files
        if [ -f $TMPDIR/battwarn15 ];
                rm $TMPDIR/battwarn15
        if [ -f $TMPDIR/battwarn10 ];
                rm $TMPDIR/battwarn10
exit 0

To get this working you’ll need to do a few things. First up, make sure ~/tmp exists, or change the TMPDIR variable to a suitable location with write permissions for your user.

You’ll also need to install this script in ~/bin or another suitable location, then configure it to launch on startup (such as in an i3 config). This script creates a means for the power script to access the dbus session for desktop notifications. The script came from this answer on stack exchange.


#include the following in a script that needs access to the dbus session
#if [ -r "$HOME/.dbus/Xdbus" ]; then
#    . "$HOME/.dbus/Xdbus"


touch $FILE
chmod 600 $FILE

exit 0

To make suspend work you’ll need to run

sudo visudo

and add a line like the following

%sudo ALL = NOPASSWD: /bin/systemctl suspend

This allows all users with sudo access to run the command to suspend using sudo without a password, which means we can run it from the script without asking for a password. If you’d prefer to allow this for just your user, replace %sudo with your user name.

Lastly, you’ll need to configure your crontab to execute this script at routine intervals. I chose every two minutes.

Run the following to edit your crontab:

crontab -e

And add this line:

*/2 * * * * /home/user/bin/power_status

Of course, make sure to replace with the path to your script. If you haven’t already, make sure the script is executable by running the following on it.

chmod +x power_status


Preivew OpenOffice/LibreOffice .odt documents in Ranger File Manager

Quick tip for those that use the Ranger file manager (which is awesome, by the way).

Ranger file previews are defined in the scope.sh configuration file. You can add your own preview mechanisms here.

To preview .odt documents in Ranger, you’ll need to install the odt2txt tool. On Ubuntu (and presumably other debian-based distros) install it using the following command:

sudo apt install odt2txt

The odt2txt command converts a .odt document into a text file and outputs it to standard output (prints it to the terminal or makes it available to be piped).

In your scopes.sh file add the following within the case “$extension” block.


odt2txt “$path” && fmt -s -w $width; exit 0;

Save the file and fire up a new instance of Ranger, then select a .odt file and you should get a text preview in the right pane.

Synaptics Clickpad Configuration for ThinkPad T440s

I briefly tried an Arch Linux install on my laptop. It wasn’t my favorite for my daily use, would probably be great for a lightweight computer or a server. In any case, the default configuration (non-) settings for the clickpad were utterly unusable, and the examples I was finding didn’t have all of the features I wanted. I dug into the man pages for the driver and put together a configuration I’m happy with, and have since rolled out to my Ubuntu 16.04 install on the same machine.

These settings enable the soft-buttons at the top of the clickpad to use with the trackpoint, creates another soft-button on the right half of the bottom of the pad for right click, disables edge scrolling, enables two-finger scrolling (horizontal and vertical), and single/double/triple-finger clicking.

This file lives (in a 16.04 Ubuntu system) in /usr/share/X11/xorg.conf.d/ . I replaced the default 50-synaptics.conf file with the following contents:

Section "InputClass"
 Identifier "touchpad"
 Driver "synaptics"
 MatchIsTouchpad "on"
 MatchDevicePath "/dev/input/event*"

 Option "ClickPad" "1"

 Option "PalmDetect" "1"
 #soft buttons at top of pad
 Option "SoftButtonAreas" "60% 0 0 2400 40% 60% 0 2400"
 Option "AreaTopEdge" "2400"

 #soft buttons at bottom of pad
 Option "HasSecondarySoftButtons" "1"
 Option "SecondarySoftBUttonAreas" "50% 0 85% 0 0 0 0 0"

 Option "HorizHysteresis" "30"
 Option "VertHysteresis" "30"
 Option "FingerLow" "30"
 Option "FingerHigh" "50"
 Option "MinSpeed" "1"
 Option "MaxSpeed" "1"
 Option "AccelerationProfile" "2"
 Option "ConstantDeceleration" "4"

 Option "VertEdgeScroll" "0"
 Option "HorizEdgeScroll" "0"
 Option "TapAndDragGesture" "0"
 Option "CircularScrolling" "0"

 Option "TapButton1" "1"
 Option "TapButton2" "3"
 Option "TapButton3" "2"
 Option "ClickFinger1" "1"
 Option "ClickFinger2" "3"
 Option "ClickFinger3" "2"

 Option "VertTwoFingerScroll" "1"
 Option "HorizTwoFingerScroll" "1"
 Option "CoastingSpeed" "0"
 Option "MaxTapTime" "125"

5Ghz Wifi Networks Not Available on Ubuntu Server Install

I needed a fresh start on my laptop (a ThinkPad T440S) and thought I would try starting with Ubuntu Server 16.04, so I can install what I want without as much Ubuntu Desktop bloat.

For networking I installed network manager and it’s corresponding tray applet control application (the network-manager and network-manager-gnome packages, respectively). Everything worked great, except that 5Ghz networks weren’t showing up to connect to.

I don’t recall where I found this solution, but the answer was to edit the file /etc/default/crda, which had this line


This needed to be changed to


Saving that change and rebooting fixed the issue – it’s possible that restarting network services might have done the same as the reboot.

libudev.so.0 not found on Ubuntu 14.04

I recently had an application that would throw this error when invoked:

error while loading shared libraries: libudev.so.0: cannot open shared object file: No such file or directory

The workaround is a symbolic link to libudev.so.1 .

In my case, this was the command that resolved the issue:

sudo ln -s /lib/x86_64-linux-gnu/libudev.so.1 /lib/x86_64-linux-gnu/libudev.so.1

Your paths may be different, but hopefully this can get you on the right track.

Volti Under Ubuntu 14.04 on a ThinkPad T440s

I’ve recently been using Openbox on Ubuntu on my Thinkpad T440s and wanted to use Volti as my volume control with a Tint2 panel.  I had trouble though, I was getting this error:

[alsactrl.py:__init__:41] can’t open Master control for card HDMI, trying to select first available mixer channel

[alsactrl.py:__init__:49] can’t open first available control for card HDMI
error: list index out of range
Traceback (most recent call last):
File “/usr/bin/volti”, line 53, in <module>
volti = main.VolumeTray()
File “/usr/lib/volti/volti/main.py”, line 124, in __init__
self.watchid = gobject.io_add_watch(fd, eventmask, self.update)
TypeError: an integer is required

The solution lies in the Volti configuration file.  It is located at ~/.config/volti/config.

In my case, the issue was with the third line under [global], the card index value.  My default card_index was 0.  Changing this to 1 and saving the file fixed the issue.