Restoring Screen Backlight Brightness in Ubuntu

One of many details available in Windows but not in Ubuntu is automatic backlight change when system switches from AC to battery. And it’s not just a dumb change to predefined value either. Every switch from AC to battery and vice versa restores the last value system had. Ubuntu on the other hand just keeps the backlight as is resulting in me manually adjusting it every time. Lookup on Internet for applications providing this functionality gave me no warm fuzzy feeling so I decided to roll my own. I mean, how hard can it be.

Well, actually annoyingly hard if you want to support every interface out there. As I wanted to support only my Dell XPS 15, I had quite a bit easier work.

The main part of the story is in two files: /sys/class/power_supply/AC/online and /sys/class/backlight/intel_backlight/brightness. All what’s needed was actually a small script handling tracking and restoring brightness values every once in a while. This is roughly what I ended with:

#!/bin/bash

STORED_AC=`cat /var/cache/.backlight.ac`
STORED_BAT=`cat /var/cache/.backlight.bat`

while(true); do
    BRIGHTNESS=`cat /sys/class/backlight/intel_backlight/brightness`
    IS_AC=`cat /sys/class/power_supply/AC/online`
    if [[ "$IS_AC" != "$LAST_AC" ]]; then
        if [[ "$IS_AC" != "0" ]]; then
            if [[ "$STORED_AC" != "" ]]; then
                echo -e "Restoring AC backlight to $STORED_AC"
                echo $STORED_AC > $FILE_BRIGHTNESS
            fi
        else
            if [[ "$STORED_BAT" != "" ]]; then
                echo -e "Restoring battery backlight to $STORED_BAT"
                echo $STORED_BAT > $FILE_BRIGHTNESS
            fi
        fi
        LAST_AC=$IS_AC
    else
        if [[ "$IS_AC" != "0" ]]; then
           if [[ "$STORED_AC" != "$BRIGHTNESS" ]]; then
               echo $BRIGHTNESS > /var/cache/.backlight.ac
               STORED_AC=$BRIGHTNESS
           fi
        else
           if [[ "$STORED_BAT" != "$BRIGHTNESS" ]]; then
               echo $BRIGHTNESS > /var/cache/.backlight.bat
               STORED_BAT=$BRIGHTNESS
           fi
        fi
    fi

    sleep 0.5
done

As you can see, the script is just checking in loop if there was an AC status change. If computer was plugged or unplugged, it simply restores the last saved value for that power state. If power status remained the same, it will track any brightness change so it’s possible to restore it later. Really simple and really working.

And yes, the script above contains no error handling. If you want to see the real stuff, it’s available on GitHub. Even better, it’s available as a Debian package if you want to install it.

Using Ctrl+Shift+Escape for System Monitor in Ubuntu

Moving from Windows to Ubuntu, there is one shortcut I surely miss - Ctrl+Shift+Escape. On Ubuntu this does absolutely nothing.

Fortunately one can always add a custom shortcut to System Monitor:

gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings \
    "['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/']"
GSCHEMA=org.gnome.settings-daemon.plugins.media-keys.custom-keybinding
GPATH=/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/
gsettings set $GSCHEMA:$GPATH name "System Monitor"
gsettings set $GSCHEMA:$GPATH command "gnome-system-monitor"
gsettings set $GSCHEMA:$GPATH binding "<Primary><Shift>Escape"

However, this is not quite “it”. The major issue is that, if System Monitor is already open, it will remain in background. As this is Linux, of course there is a command line solution for this.

First we need to install wmctrl package

sudo apt install wmctrl

Then we can setup a script to run System Monitor and activate it’s window. Since application itself is single instance, this does exactly what we need:

#!/bin/bash
nohup gnome-system-monitor >/dev/null 2>&1 & >/dev/null
wmctrl -Fa 'System Monitor'

To make it runnable, we shouldn’t forget chmod:

$ chmod +x ~/bin/system-monitor

And now finally we can adjust our key binding to call that newly created script:

gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings \
    "['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/']"
GSCHEMA=org.gnome.settings-daemon.plugins.media-keys.custom-keybinding
GPATH=/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/
gsettings set $GSCHEMA:$GPATH name "System Monitor"
gsettings set $GSCHEMA:$GPATH command "$HOME/bin/system-monitor"
gsettings set $GSCHEMA:$GPATH binding "<Primary><Shift>Escape"

I call this close enough.

Ubuntu 19.10 Fails to Install Deb File

Illustration

As I upgraded to Ubuntu 19.10, I went to install a few of my Linux applications and immediately got Failed to install file: not supported error. Debian packages that worked for me with 19.04 were suddenly causing the issue.

I traced this to my control file:

Package:        Bimil
Version:        MAJOR.MINOR
Architecture:   all
Maintainer:     Josip Medved <jmedved@jmedved.com>
Homepage:       https://www.medo64.com/bimil/
Description:    Password manager.
                A small password manager compatible with Password Safe file format.
Section:        misc
Priority:       optional
Depends:        mono-complete (>=4.2), gnupg2

While this worked fine for Ubuntu 19.04, in Ubuntu 19.10, one has to have Build-Depends value too:

Package:        Bimil
Version:        MAJOR.MINOR
Architecture:   all
Maintainer:     Josip Medved <jmedved@jmedved.com>
Homepage:       https://www.medo64.com/bimil/
Description:    Password manager.
                A small password manager compatible with Password Safe file format.
Section:        misc
Priority:       optional
Depends:        mono-complete (>=4.2), gnupg2
^^Build-Depends:  mono-complete (>=4.2)^^

Once I rebuilt package with it, my .deb files worked once again.

SIGFAULT in QVector size()

Illustration

After a long time, I started playing with C++ again - this time in the form of QT. Since I learned C++ a while ago, my code was a bit rustic and probably not following all the newest recommendations, but hey, it worked. Until I decided to change it from using QVector<std::shared_ptr<FolderItem>> to QVector<FolderItem*>. Suddenly I kept getting SIGFAULT in the most innocuous method: size().

As Google is my crutch, I did a quick search for this and found absolutely nothing useful - just other people having the same issue. After finally looking at my code, I figured why - because I was asking the wrong question. Of course there was nothing wrong with size() method in QVector class used by millions. It was me all along.

I had _folder variable in main window that I never initialized and I used it to call its method which in turn used QVector.size(). Forgetting to initialize this variable if you’re using shared_ptr is nothing - it simply ends up being null pointer and I had check for those. Once I changed to raw pointer, I lost that protection and uninitialized variable did what uninitialized variable in C++ does - pointed to “something”. Executing function “somewhere” in memory is what brought SIGFAULT - not the poor size() method.

It was all solved by something I used to do reflexively: initialize any variable declared in C++ to some value - even if that value is nullptr.

PIA in Encrypted Home Directory

Upon getting Linux Mint installed, I went ahead with installing VPN by Private Internet Access. Went through the same motions as usually albeit now with slightly different result - it wouldn’t connect.

Looking at logs ($HOME/.pia_manager/log/openvpn.log) just gave cryptic errors:

SIOCSIFADDR: Operation not permitted
: ERROR while getting interface flags: No such device
SIOCSIFDSTADDR: Operation not permitted

Quick search on internet brought me to Linux Mint forum where exactly the same problem was described. And familiarity didn’t stop there; author had one other similarity - encrypted home folder. Sounded like a perfect fit so I killed PIA client and went with slightly modified procedure:

sudo mkdir /home/pia
sudo chown -R $USER:$USER /home/pia
mv ~/.pia_manager /home/pia/.pia_manager
ln -s /home/pia/.pia_manager ~/.pia_manager

However, this didn’t help. Still the same issue in my log files. So I decided to go with atomic option. First I killed PIA client (again) and removed PIA completely together with all my modifications:

rm ~/.pia_manager
sudo rm ~/.local/share/applications/pia_manager.desktop
rm -R /home/pia

With all perfectly clean, I decided to start with fresh directory structure, exactly the same as in the original solution:

sudo mkdir -p /home/pia/.pia_manager
sudo chown -R $USER:$USER /home/pia
ln -s /home/pia/.pia_manager ~/.pia_manager

With directory in place I repeated installation of PIA client:

cd ~/Downloads
tar -xzf pia-v72-installer-linux.tar.gz
./pia-v72-installer-linux.sh

And it worked! :)