How to make LightDM suspend to RAM automatically from the login screen and lock screen in Lubuntu 18.04

My family’s desktop machine has Lubuntu 18.04 installed, which generally works well. Each family member has their own account, therefore the installation is a single-seat, multi-user system. Lubuntu 18.04 uses LightDM for the display manager, light-locker (which uses LightDM) for the screen locker, and Xfce Power Manager for power management. Xfce Power Manager enables each user to specify for their session that the machine will suspend to RAM, and to configure the duration of inactivity in their session that will trigger suspension.

However, a couple of things about this arrangement are annoying. Firstly, if two or more users happen to be logged-in simultaneously because a family member does not bother to log out, Xfce Power Manager in an inactive session will eventually suspend the machine even when another user is actively using a different session. Secondly, if nobody is logged-in and the LightDM greeter screen is displayed, the machine will not suspend to RAM automatically after a period of inactivity. The only way to get the machine to suspend to RAM if nobody is logged-in is to click on the power indicator in the greeter’s system tray and select ‘Suspend’ from the drop-down menu.

I still have not figured out how to fix the first of the above-mentioned problems, but a Web search finally turned up a fix for the second problem: a post by Linux user boyi in Arch Linux Forums thread ‘need lightdm to suspend system‘. Below I explain how I implemented this in my family’s Lubuntu 18.04 installation. Basically, when the LightDM greeter screen is displayed LightDM runs a looping shell script (lightdm_sleep.sh) that will suspend the machine after a specified time has elapsed, and either logging in or unlocking the screen will run another shell script (lightdm_kill_sleep.sh) that kills the first script. Once a user has either logged in or unlocked the screen, Xfce Power Manager in that user’s session takes over monitoring activity.

1. Pre-existing situation
When I originally installed Lubuntu 18.04 I made sure each user used the Xfce Power Manager GUI to configure suspension to RAM. Each user’s own settings are shown below:

user $ cat ~/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-power-manager.xml
<?xml version="1.0" encoding="UTF-8"?>

<channel name="xfce4-power-manager" version="1.0">
  <property name="xfce4-power-manager" type="empty">
    <property name="power-button-action" type="uint" value="3"/>
    <property name="show-tray-icon" type="bool" value="true"/>
    <property name="brightness-switch-restore-on-exit" type="int" value="1"/>
    <property name="brightness-switch" type="int" value="0"/>
    <property name="presentation-mode" type="bool" value="false"/>
    <property name="inactivity-on-ac" type="uint" value="30"/>
    <property name="blank-on-ac" type="int" value="10"/>
    <property name="dpms-on-ac-sleep" type="uint" value="0"/>
    <property name="dpms-on-ac-off" type="uint" value="0"/>
    <property name="brightness-on-ac" type="uint" value="9"/>
    <property name="lock-screen-suspend-hibernate" type="bool" value="true"/>
    <property name="logind-handle-lid-switch" type="bool" value="false"/>
    <property name="dpms-enabled" type="bool" value="false"/>
    <property name="general-notification" type="bool" value="true"/>
    <property name="sleep-button-action" type="uint" value="3"/>
    <property name="hibernate-button-action" type="uint" value="3"/>
  </property>
</channel>

Note that each user must not edit their file ~/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-power-manager.xml directly, as the properties in the Xfce Power Manager settings GUI will not be updated if they do. Users must either use the Xfce Power Manager settings GUI or use xfconf-query commands on the command line as explained on the askubuntu Web page ‘Change xfce4-power-manager option from terminal‘.

The LightDM configuration files in /etc/lightdm/lightdm.conf.d/ were as follows:

user $ ls /etc/lightdm/lightdm.conf.d/
05_lubuntu.conf  10_lubuntu.conf  unmount_FREECOM_HDD.sh

The file 05_lubuntu.conf was installed when I installed Lubuntu 18.04. The two files 10_lubuntu.conf and unmount_FREECOM_HDD.sh were previously created by me in order to unmount a permanently-connected external USB HDD when a user logs out, to avoid an access problem when another user logs in (see an earlier blog post).

user $ cat /etc/lightdm/lightdm.conf.d/10_lubuntu.conf
[Seat:*]
session-cleanup-script=/etc/lightdm/lightdm.conf.d/unmount_FREECOM_HDD.sh

2. Modifications to enable installation to suspend when no user is logged in

2.1 Specify the scripts

user $ cd /etc/lightdm/lightdm.conf.d/
user $ sudo nano 10_lubuntu.conf
user $ cat 10_lubuntu.conf 
[Seat:*]
greeter-setup-script =/etc/lightdm/lightdm.conf.d/lightdm_sleep.sh
session-setup-script=/etc/lightdm/lightdm.conf.d/lightdm_kill_sleep.sh
session-cleanup-script=/etc/lightdm/lightdm.conf.d/unmount_FREECOM_HDD.sh

2.2 Create the two scripts

user $ sudo nano lightdm_sleep.sh
user $ sudo chmod +x lightdm_sleep.sh
user $ cat lightdm_sleep.sh 
#!/bin/sh
file="/tmp/unique_identifier"
(while true; do sleep 30m; systemctl suspend; done) &
echo $! > $file
user $ sudo nano lightdm_kill_sleep.sh
user $ sudo chmod +x lightdm_kill_sleep.sh
user $ cat lightdm_kill_sleep.sh 
#!/bin/sh
file="/tmp/unique_identifier"
if [ -f "$file" ]
then
    kill `cat $file`
    rm $file
fi

2.3 Modify the existing session cleanup script to include the lightdm_kill_sleep.sh code

user $ tail -n 11 unmount_FREECOM_HDD.sh
################################################
# Code below copied from lightdm_kill_sleep.sh
file="/tmp/unique_identifier"
if [ -f "$file" ]
then
    kill `cat $file`
    rm $file
fi
# End of code copied from lightdm_kill_sleep.sh
################################################
exit 0

Of course, specifying lightdm_kill_sleep.sh would have sufficed if the installation did not already have a session cleanup script:

user $ cat 10_lubuntu.conf
[Seat:*]
greeter-setup-script =/etc/lightdm/lightdm.conf.d/lightdm_sleep.sh
session-setup-script=/etc/lightdm/lightdm.conf.d/lightdm_kill_sleep.sh
session-cleanup-script=/etc/lightdm/lightdm.conf.d/lightdm_kill_sleep.sh

3. Summary
Thus the file situation is now as follows:

user $ ls /etc/lightdm/lightdm.conf.d/
05_lubuntu.conf  10_lubuntu.conf  lightdm_kill_sleep.sh  lightdm_sleep.sh  unmount_FREECOM_HDD.sh
  • If nobody logs in after booting the machine, the machine will suspend to RAM after 30 minutes* due to greeter-setup-script.
  • If a user logs in, session-setup-script ensures only Xfce Power Manager controls suspension to RAM while the LightDM greeter screen is not displayed.
  • If a user logs out and no other user is logged in, the machine will suspend to RAM after 30 minutes* due to greeter-setup-script.
  • If a user locks the screen, the machine will suspend to RAM after 30 minutes* due to greeter-setup-script.

*Obviously the period of inactivity to trigger suspension to RAM can be configured by changing the time specified in the lightdm_sleep.sh script.

Why I switched from WhatsApp to Signal

I had avoided WhatsApp until late 2017 when one of my family installed it on my phone with the promise I would find it useful to keep in touch during a two-month work trip. Actually, it turned out to be more useful for work, as WhatsApp is the preferred method of communication at the company I visited on that trip.

Now, I was aware that Facebook acquired WhatsApp in 2014 for US$19 billion. I do not have a Facebook account and have no intention of getting one, and the fact Facebook owns WhatsApp was one of the reasons I had been reluctant to install WhatsApp in the first place. However, it didn’t take me long to like WhatsApp. The UI is very well designed, the functionality excellent and WhatsApp Web is easy and convenient to use. WhatsApp is a polished product, no doubt about that. The end-to-end encryption of WhatsApp messages is comforting, although that was not my main reason for using it. Offhand I can only think of one function I find annoying in the WhatsApp UI: when you forward a message containing an image, there is no automatic way to include the text accompanying the original message.

Recently I have read several articles stating that Facebook intends to display advertising in WhatsApp from 2020 onwards. I am sick and tired of ‘surveillance capitalism‘ tracking me and bombarding me with advertising on the Web, and this news prompted me to search for a replacement for WhatsApp. A newspaper article mentioned Signal, which I learned happens to be the source of the encryption protocol used by WhatsApp. I also learned that WhatsApp co-founder Brian Acton, who left Facebook in 2017, is Executive Chairman of the Signal Foundation, which he co-founded with the creator of Signal in 2018. So I decided to give Signal a try, and was pleasantly surprised as the UI is very similar to WhatsApp. OK, it’s not quite as polished aesthetically, but it was easy to use from the get-go.

I initially found Signal’s security-related functionality confusing. I was not sure what the so-called ‘Safety Number‘ per contact does. It turns out that you can ensure your connection with a given contact is secure by ‘verifying the Safety Number’ with that contact. From then onwards ‘Verified‘ will appear next to the contact’s name and phone number at the top of the conversation window. Verifying the Safety Number is optional, which was not clear to me initially. Each contact’s Safety Number is actually a 3 x 4 table of 5-digit numbers. You should compare the Safety Number in your app with the Safety Number in your contact’s app in a way that prevents someone intercepting you both; you can either scan a QR Code or make a visual or audible comparison of the Safety Number in your app with the Safety Number in your contact’s app. If both Safety Number tables match, you can both click on ‘Mark as verified’ in your app. The app will then warn you if a safety number has been changed because someone is intercepting your conversation (a so-called ‘man-in-the-middle’ attack).

The other security-related function I found confusing initially is resetting a session (‘Settings’ > ‘Reset session’). It is normally not necessary for you to touch this, but, if for some reason the encryption keys between two contacts no longer match (the Signal app would notify you if that occurs), either party can reset their session and force Signal to negotiate a new session.

Unlike WhatsApp, Signal does not have a Web browser UI to use on desktop machines. It used to have such an interface (using Google’s Chrome browser) but now there is a Signal desktop app instead, with versions available for Windows, Mac OS and Linux. I have Gentoo Linux on my laptops and Lubuntu Linux on the family desktop, so I have installed the Linux desktop Signal app on those machines.

Unlike WhatsApp, the phone app and the desktop app do not sync earlier messages. By this I mean that, if you install the desktop app and launch it, you will not see any earlier messages that are visible in the phone app. Similarly, if you delete a message in the phone app it will not be deleted in the desktop app, and vice versa. This is a bit of a nuisance, but is OK once you get used to it. Perhaps this has been done with security as well as storage capacity in mind; Signal stores as little of your data as possible on its servers.

Below are a few aspects of Signal functionality that I prefer over WhatsApp:

  • In the phone app it is possible to set the colour of the background (‘wallpaper’) for contacts, not just the top-level page. Thus I have made the background black for contacts to help a little to conserve the phone’s battery charge.
  • When I forward a message that includes an image, Signal includes the original text as well as the image. Further more, it gives me the opportunity to edit the message text before actually forwarding the message.
  • When I forward a message containing an image, the whole image is displayed. For example, recently someone sent me a WhatsApp message containing a cartoon which I did not understand; I did not realise there was a caption until I tapped on the image to expand it. When I forwarded the message to a Signal contact (by selecting the message in WhatsApp and tapping the Share icon), the caption at the bottom of the cartoon was visible in the resulting Signal message without needing to tap on the image.
  • The Signal phone app lets you disable link previews (a.k.a. ‘URL previews’) easily in Settings, whereas you cannot disable link previews in WhatsApp (see Should WhatsApp let you disable URL previews?).
  • Signal allows you to specify a message lifetime (‘Disappearing messages’). You can specify that messages will never be deleted automatically, or will be deleted after a certain time has elapsed (user-selectable from 5 seconds up to 1 week).
  • Although WhatsApp uses Signal’s encryption technology, unlike Signal it does not encrypt backups.
  • Unlike WhatsApp, Signal does not store message metadata.
  • Signal is fully open-source (and free of charge, with a promise of no advertising). WhatsApp is closed-source.
  • The icons of contacts are obtained from your phone’s contact list, not specified within the app itself. Some of my WhatsApp contacts have not bothered to create an icon in WhatsApp, but I had set up an icon for them in my phone’s contact list, and that icon is used in Signal.

Below are a few aspects of WhatsApp functionality that I prefer over Signal:

  • Signal has the ability to show link previews for a few Web sites (currently for Imgur, Instagram, Reddit, and YouTube only), whereas WhatsApp shows them for all sites. (From a security perspective some people might regard this as a disadvantage of WhatsApp.)
  • I prefer the white/green ticks in WhatsApp to the unfilled/filled circles with ticks in Signal, but that is purely an aesthetic opinion.
  • WhatsApp syncs all messages between the phone app and the Web UI, not just new messages, whereas Signal just syncs the messages sent and received since you installed the desktop app. (From a Security perspective some people might regard this as an advantage of Signal over WhatsApp.)

Conclusion

In general I find Signal as good as WhatsApp, if not better. I had been worried I would not find an alternative to WhatsApp that is as easy to use and as intuitive. In fact Signal is very good, and, once you understand the security features I mentioned above, it is essentially the same as WhatsApp, which was a relief to me as I like the general concept of the WhatsApp UI.

At the moment I am having to use both WhatsApp and Signal because some of my contacts only use WhatsApp, but I have already persuaded some contacts to switch to Signal and I anticipate more will migrate to Signal once WhatsApp begins displaying adverts next year.

How to chroot in Sabayon Linux

Example 1: Sabayon Linux was installed in conventional partitions

Let’s say, for example, that the installation has three partitions: /dev/sda1 (EFI System Partition formatted with FAT32); /dev/sda2 (root partition formatted with ext4); /dev/sda3 (linuxswap). Modify the mount command below accordingly if the root directory is on a different partition. In this example, /boot is on the same partition as root (/) and therefore does not need to be mounted separately.

Boot a Sabayon Linux LiveDVD or LivePenDrive, open a terminal window and enter the following commands:

sabayonuser@sabayon ~ $ su
sabayon sabayonuser # fdisk -l # Ascertain the partitioning scheme.
sabayon sabayonuser # mkdir /mnt/mychroot
sabayon sabayonuser # mount /dev/sda2 /mnt/mychroot
sabayon sabayonuser # mount --rbind /dev /mnt/mychroot/dev
sabayon sabayonuser # mount --make-rslave /mnt/mychroot/dev
sabayon sabayonuser # mount -t proc /proc /mnt/mychroot/proc
sabayon sabayonuser # mount --rbind /sys /mnt/mychroot/sys
sabayon sabayonuser # mount --make-rslave /mnt/mychroot/sys
sabayon sabayonuser # mount --rbind /tmp /mnt/mychroot/tmp
sabayon sabayonuser # chroot /mnt/mychroot /bin/bash
sabayon / # source /etc/profile
sabayon / # env-update
>>> Regenerating /etc/ld.so.cache...
sabayon / # export PS1="(chroot) $PS1"
(chroot) sabayon / # 

Now you can enter whatever commands you want in the chrooted environment. When you have finished, exit the chroot as follows:

(chroot) sabayon / # exit
exit
sabayon sabayonuser # umount -R /mnt/mychroot/tmp /mnt/mychroot/sys /mnt/mychroot/proc /mnt/mychroot/dev /mnt/mychroot
sabayon sabayonuser # shutdown -h now

Example 2: Sabayon Linux was installed in a logical volume

Let’s say, for example, that the installation has three partitions: /dev/sda1 (EFI System Partition formatted with FAT32); /dev/sda2 (/boot partition formatted with ext4); /dev/sda3 as the LVM Physical Volume with Volume Group sabayon_sabayon containing Logical Volumes root (formatted as ext4) and swap (linuxswap). Modify the mount commands accordingly if the structure is different in your case. In this example, /boot is not on the same partition as root (/) and therefore needs to be mounted separately.

Boot a Sabayon Linux LiveDVD or LivePenDrive, open a terminal window and enter the following commands:

sabayonuser@sabayon ~ $ su
sabayon sabayonuser # fdisk -l # Ascertain the partitioning scheme.
sabayon sabayonuser # pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda3
  VG Name               sabayon_sabayon
  PV Size               39.31 GiB / not usable 2.00 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              10064
  Free PE               1
  Allocated PE          10063
  PV UUID               489QRE-rvgD-JUXz-ZYad-1DM7-XNwr-lDFVNw

sabayon sabayonuser # vgdisplay
  --- Volume group ---
  VG Name               sabayon_sabayon
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  3
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               0
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               39.31 GiB
  PE Size               4.00 MiB
  Total PE              10064
  Alloc PE / Size       10063 / 39.31 GiB
  Free  PE / Size       1 / 4.00 MiB
  VG UUID               oZ2s2c-fm35-VBCT-ef3i-n8OJ-79a2-IOJ5iW

sabayon sabayonuser # lvdisplay
  --- Logical volume ---
  LV Path                /dev/sabayon_sabayon/swap
  LV Name                swap
  VG Name                sabayon_sabayon
  LV UUID                dNoMjX-yv7i-3UVR-vG2s-jsJG-PHfX-BvCYs9
  LV Write Access        read/write
  LV Creation host, time sabayon, 2018-01-05 22:55:16 +0000
  LV Status              available
  # open                 0
  LV Size                2.00 GiB
  Current LE             512
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           251:0
   
  --- Logical volume ---
  LV Path                /dev/sabayon_sabayon/root
  LV Name                root
  VG Name                sabayon_sabayon
  LV UUID                Lf81Ni-LfMu-Pifu-UUzl-ypKK-xSUc-pPfawz
  LV Write Access        read/write
  LV Creation host, time sabayon, 2018-01-05 22:55:17 +0000
  LV Status              available
  # open                 0
  LV Size                37.31 GiB
  Current LE             9551
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           251:1

sabayon sabayonuser # pvscan
File descriptor 16 (socket:[30370]) leaked on pvscan invocation. Parent PID 2635: bash
  PV /dev/sda3   VG sabayon_sabayon   lvm2 [39.31 GiB / 4.00 MiB free]
  Total: 1 [39.31 GiB] / in use: 1 [39.31 GiB] / in no VG: 0 [0   ]
sabayon sabayonuser # vgscan
File descriptor 16 (socket:[30370]) leaked on vgscan invocation. Parent PID 2635: bash
  Reading volume groups from cache.
  Found volume group "sabayon_sabayon" using metadata type lvm2
sabayon sabayonuser # vgchange -ay
File descriptor 16 (socket:[30370]) leaked on vgchange invocation. Parent PID 2635: bash
  2 logical volume(s) in volume group "sabayon_sabayon" now active
sabayon sabayonuser # lvscan
File descriptor 16 (socket:[30370]) leaked on lvscan invocation. Parent PID 2635: bash
  ACTIVE            '/dev/sabayon_sabayon/swap' [2.00 GiB] inherit
  ACTIVE            '/dev/sabayon_sabayon/root' [37.31 GiB] inherit
sabayon sabayonuser # mkdir /mnt/mychroot
sabayon sabayonuser # mount /dev/sabayon_sabayon/root /mnt/mychroot
sabayon sabayonuser # mount /dev/sda2 /mnt/mychroot/boot
sabayon sabayonuser # mount --rbind /dev /mnt/mychroot/dev
sabayon sabayonuser # mount --make-rslave /mnt/mychroot/dev
sabayon sabayonuser # mount -t proc /proc /mnt/mychroot/proc
sabayon sabayonuser # mount --rbind /sys /mnt/mychroot/sys
sabayon sabayonuser # mount --make-rslave /mnt/mychroot/sys
sabayon sabayonuser # mount --rbind /tmp /mnt/mychroot/tmp
sabayon sabayonuser # chroot /mnt/mychroot /bin/bash
sabayon / # source /etc/profile
sabayon / # env-update
>>> Regenerating /etc/ld.so.cache...
sabayon / # export PS1="(chroot) $PS1"
(chroot) sabayon / # 

Now you can enter whatever commands you want in the chrooted environment. For example:

(chroot) sabayon / # equo version
319

When you have finished, exit the chroot as follows:

(chroot) sabayon / # exit
exit
sabayon sabayonuser # umount -R /mnt/mychroot/tmp /mnt/mychroot/sys /mnt/mychroot/proc /mnt/mychroot/dev /mnt/mychroot/boot /mnt/mychroot
sabayon sabayonuser # equo version
310
sabayon sabayonuser # shutdown -h now

In the example above I have used the ‘equo version‘ command in the chroot environment and in the LiveDVD environment, simply to illustrate that the two environments are not the same. As you can see, the LiveDVD I used has the package equo-310 installed, whereas the installation on the HDD has equo-319 installed.

By the way, if using the Sabayon Linux KDE LiveDVD/LivePenDrive, I discovered that the LVM command ‘vgchange -ay‘ can be omitted if I launch the KDE Partition Manager:

sabayon sabayonuser # partitionmanager

I just look at the partitions in the KDE Partition Manager’s GUI and quit the application (‘File’ > ‘Quit’).

How to change the keymap (keyboard layout) used by the GRUB shell in Gentoo Linux

The default keymap in the GRUB shell is US English. Because Linux has not yet been booted, the GRUB keymap is not governed by the keymap for the Linux console specified in /etc/conf.d/keymaps in the case of OpenRC, or in /etc/vconsole.conf in the case of systemd. This can be inconvenient if your keyboard has a different layout and you need to use the GRUB Rescue Shell. Below I explain how I configured my Gentoo Linux installation to be able to use a different keyboard layout in the GRUB shell.

There are, however, certain limitations to the keymap in the GRUB shell. The official GRUB documentation states the following:

17.4 Input terminal

Firmware console on BIOS, IEEE1275 and ARC doesn’t allow you to enter non-ASCII characters. EFI specification allows for such but author is unaware of any actual implementations. Serial input is currently limited for latin1 (unlikely to change). Own keyboard implementations (at_keyboard and usb_keyboard) supports any key but work on one-char-per-keystroke. So no dead keys or advanced input method. Also there is no keymap change hotkey. In practice it makes difficult to enter any text using non-Latin alphabet. Moreover all current input consumers are limited to ASCII.

Note that the GRUB documentation states ‘ASCII’, not ‘Extended ASCII’. ASCII is limited to codes 000 to 127 (see the character table in e.g. http://www.asciitable.com/).

Some Linux distributions have the utility grub-kbdcomp to generate a GRUB keyboard layout file. grub-kbdcomp is simply a shell script that is a wrapper for the Debian ckbcomp utility and grub-mklayout. There is a Gentoo Portage ebuild for ckbcomp:

root # eix ckbcomp
[I] sys-apps/ckbcomp
     Available versions:  (~)1.164
     Homepage:            https://anonscm.debian.org/cgit/d-i/console-setup.git
     Description:         Compile an XKB keymap for loadkeys

However, I noticed that the latest version currently available in Debian is 1.191 (https://salsa.debian.org/installer-team/console-setup.git), so I created an ebuild ckbcomp-1.191.ebuild in a local overlay on one of my laptops running Gentoo Linux Stable Branch, and I installed ckbcomp-1.191.

# Copyright 1999-2019 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

EAPI=6

DESCRIPTION="Compile an XKB keymap for loadkeys"
HOMEPAGE="https://salsa.debian.org/installer-team/console-setup.git"

if [[ ${PV} == 9999 ]]; then
        inherit git-r3
        EGIT_REPO_URI="https://salsa.debian.org/installer-team/console-setup.git"
else
        SRC_URI="https://salsa.debian.org/installer-team/console-setup/-/archive/${PV}/${P}.tar.gz -> ${P}.tar.gz"
        KEYWORDS="~amd64"
        S="${WORKDIR}"
fi

LICENSE="GPL-2"
SLOT="0"

DEPEND=""
RDEPEND="
        dev-lang/perl:*
        sys-apps/kbd
        x11-misc/xkeyboard-config"

src_compile() {
        :
}

src_install() {
        dobin console-setup-${PV}-*/Keyboard/ckbcomp
}

I have tried the above-mentioned ckbcomp command on my PC BIOS Core i7 laptop running Gentoo Stable with OpenRC and GRUB Version 2.02-r3:

root # eix -I grub
[I] sys-boot/grub
     Available versions:  (2) 2.02-r3(2/2.02-r3)^st **9999(2/9999)^st
       {debug device-mapper doc efiemu +fonts libzfs mount multislot nls sdl static test +themes truetype GRUB_PLATFORMS="coreboot efi-32 efi-64 emu ieee1275 loongson multiboot pc qemu qemu-mips uboot xen xen-32"}
     Installed versions:  2.02-r3(2/2.02-r3)^st(02:33:36 23/03/19)(fonts nls sdl themes truetype -debug -device-mapper -doc -efiemu -libzfs -mount -multislot -static -test GRUB_PLATFORMS="pc -coreboot -efi-32 -efi-64 -emu -ieee1275 -loongson -multiboot -qemu -qemu-mips -uboot -xen -xen-32")
     Homepage:            https://www.gnu.org/software/grub/
     Description:         GNU GRUB boot loader

I used the following steps:

1. Installed sys-apps/ckbcomp.

root # emerge ckbcomp
root # eix ckbcomp
[I] sys-apps/ckbcomp
     Available versions:  (~)1.164 (~)1.191[1]
     Installed versions:  1.191[1](22:09:15 20/04/19)
     Homepage:            https://salsa.debian.org/installer-team/console-setup.git
     Description:         Compile an XKB keymap for loadkeys

[1] "local_overlay" /usr/local/portage

2. Created a new sub-directory to store the GRUB keyboard layout files.

root # mkdir /boot/grub/layouts

3. Converted the X11 keymap to the GRUB keymap. The option for ckbcomp must exist in the directory /usr/share/X11/xkb/symbols/ for this to work.

root # ckbcomp gb extd | grub-mklayout -o /boot/grub/layouts/gb.gkb
Unknown keyboard scan identifier Meta_Tab
Unknown keyboard scan identifier Meta_Tab
Unknown keyboard scan code 0x54
Unknown keyboard scan code 0x65
Unknown keyboard scan code 0x7f

I used the following commands to generate a br.gkb (Brazilian Portuguese keymap) file and a us.gkb (US English keymap) as well, as it is possible to switch keyboard layouts from the GRUB command line using the keymap command, as I show further on:

root # ckbcomp br nodeadkeys | grub-mklayout -o /boot/grub/layouts/br.gkb
Unknown keyboard scan identifier Meta_Tab
Unknown keyboard scan identifier Meta_Tab
Unknown keyboard scan identifier KP_Comma
Unknown keyboard scan identifier KP_Comma
Unknown keyboard scan identifier KP_Comma
Unknown keyboard scan identifier KP_Comma
Unknown keyboard scan code 0x54
Unknown keyboard scan code 0x65
Unknown keyboard scan code 0x7f
root # ckbcomp us | grub-mklayout -o /boot/grub/layouts/us.gkb
Unknown keyboard scan identifier Meta_Tab
Unknown keyboard scan identifier Meta_Tab
Unknown keyboard scan code 0x54
Unknown keyboard scan code 0x65
Unknown keyboard scan code 0x7f

The resulting files can be seen in the directory /boot/grub/layouts/:

root # ls -la /boot/grub/layouts
total 11
drwxr-xr-x 2 root root 1024 Apr 21 21:20 .
drwxr-xr-x 7 root root 1024 Nov 26 00:01 ..
-rw-r--r-- 1 root root 2572 Apr 21 21:29 br.gkb
-rw-r--r-- 1 root root 2572 Apr 21 21:29 gb.gkb
-rw-r--r-- 1 root root 2572 Apr 21 21:30 us.gkb

4. Append ‘GRUB_TERMINAL_INPUT=at_keyboard‘ to /etc/default/grub.

root # grep GRUB_TERMINAL_INPUT /etc/default/grub
GRUB_TERMINAL_INPUT="at_keyboard"

5. Add ‘insmod‘ and ‘keymap‘ lines to /etc/grub.d/40_custom as shown below.

root # tail -n 2 /etc/grub.d/40_custom
insmod keylayouts
keymap $prefix/layouts/gb.gkb

6. Check what locales are available for the keymap.

root # locale --all-locales | grep -i gb
en_GB
en_GB.iso88591
en_GB.utf8

7. Add ‘locale=en_GB‘ to GRUB_CMDLINE_LINUX.

root # grep locale /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="locale=en_GB i915.modeset=1 rcutree.rcu_idle_gp_delay=1 acpi_enforce_resources=lax reboot=force raid=noautodetect resume=/dev/sda2"

8. Regenerate the grub.cfg file.

root # grub-mkconfig -o /boot/grub/grub.cfg
root # grep terminal_input /boot/grub/grub.cfg
terminal_input at_keyboard
root # grep gkb /boot/grub/grub.cfg
keymap $prefix/layouts/gb.gkb
root # grep layouts /boot/grub/grub.cfg
insmod keylayouts
keymap $prefix/layouts/gb.gkb

9. If the machine uses UEFI rather than PC BIOS, update the GRUB files in the EFI directory.

root # grub-install --efi-directory=/boot/efi

10. Reboot to check if the gb keymap has been loaded for the GRUB shell.

root # reboot

When I press ‘c‘ when the GRUB menu appears, I now see the following if I press each key on the second-to-last row of keys on the keyboard:

grub> \zxcvbnm,./

That corresponds to a British English keyboard layout. As I mentioned before, due to GRUB’s limitations only standard ASCII chars are possible, so it is not possible to type characters such as é and è, or symbols such as £ and etc. on the GRUB command line, whatever the keymap.

You can tell if the GRUB keylayouts module is loaded by entering the following command on the GRUB command line:

lsmod

Below is what I then see on the screen of a PC BIOS machine running up-to-date Gentoo Linux (Stable Branch) when I press ‘c‘ when the GRUB menu is displayed.


                                                GNU GRUB  version 2.02~beta3

   Minimal BASH-like line editing is supported. For the first word, TAB lists possible command completions. Anywhere else TAB lists possible device or file completions. ESC at any time exits.


grub> lsmod
Name    Ref Count       Dependencies
minicmd 1
gfxterm_background      1              bitmap,video,extcmd,gfxterm,bitmap_scale,video_colors
bitmap_scale    2               bitmap
video_colors    2
png     1               bitmap,bufio
bitmap  7
search  1               search_label,extcmd,search_fs_file,search_fs_uuid
search_label    2
search_fs_file  2
search_fs_uuid  2
at_keyboard     1               boot,keylayouts
keylayouts      3
gfxterm 3               video,font
all_video       1               video_cirrus,video_bochs,vga,vbe
video_cirrus    2               video_fb,pci,video
video_bochs     2               video_fb,pci,video
pci     6
vga     2               video_fb,video
vbe     2               video_fb,video
video_fb        12
font    5               video,bufio
video   24
loadenv 1               extcmd,disk
disk    2
test    1
normal  1               gettext,boot,extcmd,bufio,crypto,terminal
gzio    0
gettext 3
boot    4
extcmd  8
bufio   10
crypto  2
terminal        2
biosdisk        1
part_msdos      2
ext2    4               fshelp
fshelp  5
grub>

Shown below is what I see when I perform the following steps on the GRUB command line:

  1. press each key on the second-to-last line of keys on the keyboard and press Enter;
  2. check which GRUB terminal input module is loaded;
  3. change from the British English keyboard layout to the Brazilian Portuguese keyboard layout;
  4. press each key on the second-to-last line of keys on the keyboard and press Enter;
  5. switch back to the British English keyboard layout;
  6. press each key on the second-to-last line of keys on the keyboard and press Enter;
  7. switch to the US English keyboard layout;
  8. press each key on the second-to-last line of keys on the keyboard and press Enter;
  9. switch back to the British English keyboard layout.

In each case the output on the screen is correct for the keyboard layout selected:

grub> \zxcvbnm,./
error: can't find command `zxcvbnm,./'.
grub> terminal_input
Active input terminals:
at_keyboard
Available input terminals:
console serial_* serial
grub> keymap br
grub> \zxcvbnm,.;
error: can't find command `zxcvbnm,.;'.
grub> keymap gb
grub> \zxcvbnm,./
error: can't find command `zxcvbnm,./'.
grub> keymap us
grub> <zxcvbnm,./
error: syntax error.
error: Incorrect command.
error: syntax error.
grub> keymap gb
grub> 

There is one more caveat…

When the GRUB menu first appears at boot, the following lines are still displayed at the bottom of the GRUB menu:

   Use the ↑ and ↓ keys to select which entry is highlighted.
   Press enter to boot the selected OS, `e' to edit the commands before booting or `c' for a command-line.
The highlighted entry will be executed automatically in 4s.

However, the highlighted entry on the GRUB menu is no longer executed automatically and I have to press ENTER in order to get GRUB to boot Linux. That is not a big deal in my case.

Automatically clearing the /usr/tmp/portage directory in Gentoo Linux

Gentoo Linux has been in use for nine years on one of my old laptops. A couple of days ago I performed the usual rolling update of the installation, but the latest version of a large package that normally takes several hours to compile failed to compile due to a lack of disk space. Sure enough, the command ‘df -h‘ showed me that the root partition was full. After a little digging I discovered that the directory /usr/tmp/portage/ contained a whopping 30GB of directories and files.

Portage uses the directory /usr/tmp/portage/ as a temporary store for the package source code when merging a package. The temporary files are not deleted if a merge fails, but the emerge command should delete them on the next merge of that package. On the other hand the ebuild command does not delete the temporary files, although normally you only use the ebuild command if you are creating a manifest.

Anyway, in the nine years that Gentoo Linux has been installed on the laptop I had never bothered to check that /usr/tmp/portage/ was actually empty, and its contents had slowly increased. The cure to my immediate problem was simply to empty the directory:

root # rm -rf /usr/tmp/portage/*

I doubt the laptop would still be working by the time /usr/tmp/portage would become that full again, but the situation got me thinking: What if I were to create a script to delete the temporary directories and files in /usr/tmp/portage/ at shutdown?

Gentoo Linux on this laptop uses OpenRC so I simply created a file /etc/local.d/99delete_tmp_files_from_failed_merges.stop containing the following code:

#!/bin/bash
# If root partition is more than 90% full, delete any temporary directories and
# files that were left in /var/tmp/portage/ instead of being deleted.
#
# The root partition is on /dev/sda6 and the emerge command must not be running.
#
if [ `pgrep -c emerge` -eq 0 ] && [ `df | awk '/sda6/ {print $5}' | awk -F% '{print $1}'` -gt 90 ]; then
    rm -rf /usr/tmp/portage/*
fi

I made the script executable:

root # chmod +x /etc/local.d/99delete_tmp_files_from_failed_merges.stop

Now, if the root partition is more than 90% full when I shut down the laptop, the script will automatically empty that directory. One less thing to think about.

KDE Device Notifier work-around

KDE Device Notifier can be annoying sometimes. The problem is that clicking on the Eject icon in Device Notifier (tooltip ‘Click to safely remove this device’) both unmounts and ejects the device (two separate commands). Of course, in the case of a USB device the device remains physically connected until you pull out the USB plug. You cannot re-mount the device in KDE Device Notifier until you unplug it and plug it in again. However, there is a hack that can help somewhat, as I explain below.

Firstly, note that it is possible to mount and unmount drives by using the ‘udisksctl’ command. For example, consider one of my USB HDDs which has the label ‘USBHDD01’ (I assign a label to all HDD partitions, be they on internal HDDs or on external HDDs/pendrives). It is possible to unmount the specific USB device and remount it by using the following commands:

fitzcarraldo@clevow230ss ~ $ udisksctl unmount -b /dev/disk/by-label/USBHDD01
Unmounted /dev/sdb1.
fitzcarraldo@clevow230ss ~ $ udisksctl mount -b /dev/disk/by-label/USBHDD01
Mounted /dev/sdb1 at /run/media/fitzcarraldo/USBHDD01.

In both the above cases the USB device remains visible in Device Notifier. I have created a couple of executable Desktop Configuration Files in the directory ~/Desktop/ which I can double-click to run each of the above commands. I have given each of them an appropriate icon:

The file ~/Desktop/Mount_USBHDD01.desktop contains the following:

[Desktop Entry]
Comment[en_GB]=Mount USB HDD with label USBHDD01
Comment=Mount USB HDD with label USBHDD01
Exec=udisksctl mount -b /dev/disk/by-label/USBHDD01
GenericName[en_GB]=Mount_USBHDD01
GenericName=Mount_USBHDD01
Icon=media-mount
MimeType=
Name[en_GB]=Mount_USBHDD01
Name=Mount_USBHDD01
Path=
StartupNotify=true
Terminal=false
TerminalOptions=
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-KDE-SubstituteUID=false
X-KDE-Username=fitzcarraldo

The file ~/Desktop/Unmount_USBHDD01.desktop contains the following:

[Desktop Entry]
Comment[en_GB]=Unmount USB HDD with label USBHDD01
Comment=Unmount USB HDD with label USBHDD01
Exec=udisksctl unmount -b /dev/disk/by-label/USBHDD01
GenericName[en_GB]=Unmount_USBHDD01
GenericName=Unmount_USBHDD01
Icon=media-eject
MimeType=
Name[en_GB]=Unmount_USBHDD01
Name=Unmount_USBHDD01
Path=
StartupNotify=true
Terminal=false
TerminalOptions=
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-KDE-SubstituteUID=false
X-KDE-Username=fitzcarraldo

(N.B. Since I could not find a media-unmount icon, I have used the media-eject icon to represent Unmount.)

This is not perfect in the sense that the device will still disappear from Device Notifier if you click on the Eject icon in Device Notifier. But at least I can avoid doing that until I really do want to unplug the device from my laptop. In other cases I simply double-click on the Mount_USBHDD01 icon and Unmount_USBHDD01 icon on my Desktop to mount and unmount the USB device as many times as I need to.

HEIC image files in Linux

I was at an event recently where the attendees were asked to upload their camera and smartphone photos and videos to a shared Google Drive folder. Some of the uploaded photo files have a .HEIC (High Efficiency Image Container) extension, which I had not come across before. I have since learnt that these HEIC files were produced by iPhones running iOS 11, encoded using the HEIF (High Efficiency Image File) format. Apparently the HEIF format is superior to the JPEG format in a number of ways (see the links at the end of my post, especially the image examples given by Nokia), although it is subject to patents and therefore I believe there are certain constraints to coding image files in HEIC format. Anyway, I’ll leave you to read the fine print. My interest was simply because I wanted to be able to download the above-mentioned photo files and view them all in the file managers and image-viewing applications in Linux and Android on my various devices.

Now, I can browse and view the above-mentioned shared HEIC images in Google Drive in the Firefox and Chrome browsers in Linux, although an ownCloud site viewed using the same browsers displays the HEIC files as grey icons that can only be downloaded, not opened and viewed in the browser. I also found that Cirrus, the Android app for ownCloud that I use on my Galaxy Note 8 phone, cannot display HEIC photos either.

I downloaded the HEIC files to a machine running Lubuntu 18.04 and to a machine running Gentoo Linux. The file manager PCManFM in Lubuntu 18.04 displays grey icons rather than thumbnails for these HEIC files, and KDE’s Dolphin 18.08.3 file manager in Gentoo Linux displays green image icons rather than thumbnails for them. As far as Linux image viewers go, in Lubuntu 18.04 I find that GPicView 0.2.5 and Geeqie 1.4 cannot display HEIC images, and in Gentoo Linux KDE I find that GQview 2.1.5-r1, Okular 18.08.3 and Gwenview 18.08.3 cannot display HEIC images. So I set about converting all the HEIC files to JPG files. I managed to do this but needed to use a range of tools, as illustrated by a couple of examples below for Lubuntu 18.04 and Gentoo Linux. This post might seem long-winded but perhaps may be of help to Linux users coming across .HEIC files for the first time.

From the .HEIC files I had downloaded I picked one at random to try and convert to a JPG file: IMG_3706.HEIC. Its EXIF data confirms it is an HEIC file:

user $ exiftool IMG_3706.HEIC | grep "File Type"
File Type                       : HEIC
File Type Extension             : heic
user $ exiftool IMG_3706.HEIC | grep "Camera Model"
Camera Model Name               : iPhone 7 Plus

Several of the files with the .HEIC suffix that I downloaded were not real HEIC files according to their EXIF data:

user $ exiftool IMG_9474.HEIC | grep "File Type"
File Type                       : JPEG
File Type Extension             : jpg
user $ exiftool IMG_9474.HEIC | grep "Camera Model"
Camera Model Name               : iPhone 8

Those files were apparently treated as JPEG files by the tools I mention below, so I have omitted the results for those ‘false’ HEIC files.

Lubuntu 18.04

1. I installed the libheif example tools:

user $ sudo apt install libheif-examples

2. I used the heif-info command to check the file:

user $ heif-info IMG_3706.HEIC 
image: 3024x4032 (id=49), primary
  thumbnail: 240x320
  alpha channel: no
  depth channel: no

3. I tried to convert the file using the heif-convert command:

user $ heif-convert IMG_3706.HEIC IMG_3706.jpg
File contains 1 images
Written to IMG_3706.jpg

4. Apparently Imagemagick >=7.0.7-22 compiled with --with-libheif is supposed to be able to convert HEIC files to JPG. Anyway, I tried to convert the file using the current version of Imagemagick in Lubuntu 18.04 (the current package version is 8:6.9.7.4+dfsg-16ubuntu6.4):

user $ convert IMG_3706.HEIC IMG_3706a.jpg
convert-im6.q16: no decode delegate for this image format `HEIC' @ error/constitute.c/ReadImage/504.
convert-im6.q16: no images defined `IMG_3706a.jpg' @ error/convert.c/ConvertImageCommand/3258.

5. Apparently the GIMP >=2.10.2 supports HEIF by using heif-gimp-plugin. Anyway, I tried to open the file with the current version of the GIMP in Lubuntu 18.04 (the current package version is 2.8.22-1). The GIMP launches and pops-up a window with the title ‘GIMP Message’ containing the following message and an ‘OK’ button:

GIMP Message
Opening /home/fitzcarraldo/IMG_3706.HEIC’ failed: Unknown file type

6. I used the online tool ‘libheif decoder demo’ (https://strukturag.github.io/libheif/) in a browser window. This can load the file IMG_3706.HEIC (‘Browse…’ button) and convert it (‘Save image…’ button) to IMG_3706.jpeg.

Gentoo Linux with KDE 5

1. I installed the libheif example tools implicitly by re-merging Imagemagick with USE="heif", which installs libheif.

root # cat /etc/portage/package.use/imagemagick 
media-gfx/imagemagick heif
root # emerge imagemagick

2. I used the heif-info command to check the file:

user $ heif-info IMG_3706.HEIC  
image: 3024x4032 (id=49), primary
  thumbnail: 240x320
  alpha channel: no
  depth channel: no

3. I tried to convert the file using the heif-convert command:

user $ heif-convert IMG_3706.HEIC IMG_3706.jpg
File contains 1 images
Written to IMG_3706.jpg

4. I tried to convert the file using Imagemagick >=7.0.7-22 compiled with --with-libheif (Imagemagick merged with USE="heif"):

user $ convert IMG_3706.HEIC IMG_3706a.jpg
user $

So Imagemagick 7.0.8.16 in Gentoo has no trouble with the file IMG_3706.HEIC.

5. I tried to open the file with the GIMP >=2.10.2, which supports HEIF using heif-gimp-plugin (GIMP >=2.10.6-r1 with USE="heif" in the case of Gentoo Linux)

First I re-merged the GIMP with the heif USE flag:

root # cat /etc/portage/package.accept_keywords/gimp
=media-gfx/gimp-2.10.8-r1 ~amd64
# required by media-gfx/gimp-2.10.8-r1::gentoo
=media-libs/libmypaint-1.3.0 ~amd64
# required by media-gfx/gimp-2.10.8-r1::gentoo
=media-gfx/mypaint-brushes-1.3.0-r1 ~amd64
# required by media-gfx/gimp-2.10.8-r1::gentoo
=media-libs/gegl-0.4.12 ~amd64
# required by media-gfx/gimp-2.10.8-r1::gentoo
=media-libs/babl-0.1.60 ~amd64
root # cat /etc/portage/package.use/gimp
media-gfx/gimp heif
root # emerge -1vp gimp

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N    ~] media-gfx/mypaint-brushes-1.3.0-r1:1.0::gentoo  2,390 KiB
[ebuild     U ~] media-libs/babl-0.1.60::gentoo [0.1.38::gentoo] USE="(-altivec)" CPU_FLAGS_X86="mmx sse sse2 sse3%* sse4_1 -f16c" 670 KiB
[ebuild  N     ] media-libs/gexiv2-0.10.8::gentoo  USE="-introspection -python -static-libs -test -vala" PYTHON_TARGETS="python2_7 python3_6 -python3_4 -python3_5" 620 KiB
[ebuild  NS   ~] media-libs/gegl-0.4.12:0.4::gentoo [0.2.0-r5:0::gentoo] USE="cairo ffmpeg introspection lcms openexr sdl svg tiff v4l -debug -jpeg2k -lensfun -libav -raw -test -umfpack -vala -webp" CPU_FLAGS_X86="mmx sse" 6,900 KiB
[ebuild  NS    ] media-libs/gegl-0.3.26:0.3::gentoo [0.2.0-r5:0::gentoo] USE="cairo ffmpeg introspection lcms openexr sdl svg tiff v4l -debug -jpeg2k -lensfun -raw -test -umfpack -vala -webp" CPU_FLAGS_X86="mmx sse" 6,378 KiB
[ebuild  N    ~] media-libs/libmypaint-1.3.0::gentoo  USE="gegl nls openmp -introspection" 428 KiB
[ebuild     U ~] media-gfx/gimp-2.10.8-r1:2::gentoo [2.8.22-r1:2::gentoo] USE="alsa heif%* mng openexr%* udev wmf -aalib (-altivec) (-aqua) -debug -doc -gnome -jpeg2k -postscript -python -smp -test -unwind% -vector-icons% -webp% -xpm (-bzip2%*) (-curl%) (-dbus%*) (-exif%*) (-jpeg%*) (-lcms%*) (-pdf%*) (-png%*) (-svg%*) (-tiff%*)" CPU_FLAGS_X86="mmx sse" PYTHON_TARGETS="python2_7" 31,206 KiB

Total: 7 packages (2 upgrades, 3 new, 2 in new slots), Size of downloads: 48,591 KiB

I then launched the GIMP and successfully opened the file IMG_3706.HEIC, and I was able to export it as IMG_3706.jpg.

6. As would be expected, the online tool ‘libheif decoder demo’ (https://strukturag.github.io/libheif/) behaves exactly the same in Gentoo Linux as it does in Lubuntu 18.04 (see earlier).

Summary

So there you have it; if the Linux file manager and/or image viewing applications you use cannot already handle HEIC files, the tools in Linux that I found may work are as follows:

  • heif-convert (from the package libheif-examples in Ubuntu/Lubuntu, or from from the package libheif in Gentoo).
  • Imagemagick (not every version).
  • The GIMP (not every version).
  • the online tool ‘libheif decoder demo’ (https://strukturag.github.io/libheif/).

I have not tried the copyright open-source code from Nokia (see link under Further Reading below), qt-heif-image-plugin and tifig (not in active development). If you have had success using another tool to convert HEIC files, please post a comment below for the benefit of other users, giving the name of the tool, the package name and version, and the Linux distribution (including release number, if not a rolling distribution).

Further reading

  1. Wikipedia – High Efficiency Image File Format
  2. Lifewire – What Are HEIF and HEIC, and Why Is Apple Using Them?
  3. Nokia – High Efficiency Image File Format (HEIF)
  4. libheif – a ISO/IEC 23008-12:2017 HEIF file format decoder and encoder
  5. askubuntu – Any app on Ubuntu to open HEIF (.heic, High Efficiency Image File Format) pictures?

How to display the times in various time zones from the LXDE Panel

I normally check the time in the time zone of family, friends and colleagues who live in various places around the World before I call or message them. In KDE Plasma on my laptop it is possible to configure the digital clock widget to display the times in a list of time zones of my choice when I hover the mouse pointer over the widget. However, my family’s PC has Lubuntu 18.04 installed, which uses LXDE, and the digital clock on the LXDE Panel does not have that ability. Therefore I installed the GUI utility gworldclock in Lubuntu 18.04:

$ sudo apt-get install gworldclock

I added it to the ‘Application Launch and Task Bar’ plugin on the LXDE Panel, and a clock icon is now displayed on the Panel.

gworldclock icon on Application Launch and Task Bar on LXDE Panel

gworldclock icon on Application Launch and Task Bar on LXDE Panel

When I click the clock icon, a window opens on the Desktop and displays the date and time at each of the World locations I configured in gworldclock (‘Options’ > ‘Add Timezone’). Excellent, and almost as convenient as the World time feature in the Digital Clock widget in KDE Plasma 5.

gworldclock window default size

gworldclock window default size

I have configured gworldclock to display a list of ten additional time zones when I click on the clock icon on the Application Launch and Task Bar on the Panel. However, the size of the pop-up gworldclock window was relatively small; only six of the eleven time zones were visible, so I had to use the window’s scroll bar in order to view some of the configured time zone entries. I therefore made some changes in LXDE in order to display a larger gworldclock window showing all eleven time zones. This is how I did it.

1. I installed wmctrl:

$ sudo apt-get install wmctrl

2. I created a hidden Bash script ~/.gworldclockfitzcarraldo.sh containing the following:

#!/bin/bash
gworldclock &
sleep 0.5s
wmctrl -F gworldclock -r gworldclock -e 0,500,300,300,340

and made it executable:

$ chmod +x ~/.gworldclockfitzcarraldo.sh

See man wmctrl for the meaning of the options in the above-mentioned Bash script.

3. I created the Desktop Configuration File ~/.local/share/applications/gworldclockfitzcarraldo.desktop containing the following:

[Desktop Entry]
Comment=See the time in other timezones
Name=gworldclock
GenericName=World Clock
Encoding=UTF-8
Comment[fr]=Voir l'heure dans d'autres fuseaux horaires
Exec=/home/fitzcarraldo/.gworldclockfitzcarraldo.sh
Terminal=false
Type=Application
Icon=gworldclock
Categories=Utility;Clock;HamRadio

4. I edited the file ~/.config/lxpanel/Lubuntu/panels/panel and added an entry for the new Desktop Configuration File to the end of list for the Application Launch and Task Bar, as shown in the following excerpt from the file:

Plugin {
  type=launchtaskbar
  Config {
    Button {
      id=pcmanfm.desktop
    }
    Button {
      id=firefox.desktop
    }
    Button {
      id=google-chrome.desktop
    }
    Button {
      id=gedit.desktop
    }
    Button {
      id=lxterminal.desktop
    }
    Button {
      id=galculator.desktop
    }
    Button {
      id=gworldclockfitzcarraldo.desktop
    }
  }
}

Then I logged out and back in again. Now, when I click on the clock icon on the Panel, the gworldclock window opens at the location and size specified by the wmctrl command in the Bash script I created.

gworldclock window resized by the Bash script

gworldclock window resized by the Bash script

Configure a keyboard shortcut in Lubuntu 18.04 to take a screenshot of a screen region

As installed, Lubuntu 18.04 is configured so that the user can capture a screenshot of the whole screen by pressing the PrtScrn key, and a screenshot of the active window by pressing Alt+PrtScrn. However, no keyboard shortcut is configured to enable the user to capture a user-specified region of the screen.

Now, as it happens, the ‘-s‘ option of the scrot command allows a region of the screen to be captured and saved. The man page for scrot tells us:

-s, --select
Interactively select a window or rectangle with the mouse.

So here is how to configure a keyboard shortcut to do that in Lubuntu 18.04.

Open the file ~/.config/openbox/lubuntu-rc.xml in a text editor (either nano from the command line or LXTerminal from the GUI) and look for the following lines:

    <keybind key="Print">
      <action name="Execute">
        <command>lxsession-default screenshot</command>
      </action>
    </keybind>
    <keybind key="A-Print">
      <action name="Execute">
        <command>lxsession-default screenshot window</command>
      </action>
    </keybind>

Append the following lines to that group of lines:

    <keybind key="C-A-Print">
      <action name="Execute">
        <command>scrot -s</command>
      </action>
    </keybind>

The new group of lines should then look like this:

    <keybind key="Print">
      <action name="Execute">
        <command>lxsession-default screenshot</command>
      </action>
    </keybind>
    <keybind key="A-Print">
      <action name="Execute">
        <command>lxsession-default screenshot window</command>
      </action>
    </keybind>
    <keybind key="C-A-Print">
      <action name="Execute">
        <command>scrot -s</command>
      </action>
    </keybind>

Now logout and login again.

If you now press Ctrl+Alt+PrtScrn and use your mouse to select a rectangular region of the screen, a screenshot of that region will be saved automatically to your home directory. Simple.

You just have to remember:

PrtScrn — Captures the entire screen.
Alt+PrtScrn — Captures the active window.
Ctrl+Alt+PrtScrn — Captures the area of the screen you select with the mouse.

How to create missing favicons for your bookmarks in Firefox Quantum for Linux

Prior to the advent of Firefox Quantum, several add-ons were available that enabled you to replace the favicons of bookmarks in Firefox, or to create custom favicons for bookmarks lacking a favicon. One of my favourite such add-ons was Favicon Picker 3. However, Firefox Quantum currently lacks an add-on that would enable you to insert a favicon of your choice for bookmarks without one. This has annoyed me for some time, as my bookmarks menu in Firefox includes several Web sites without favicons. Today I found a 2013 post ‘How to change Firefox bookmark icons (favicons) without extensions or addons!‘ for Windows predating Firefox Quantum. I have applied a similar procedure for Firefox Quantum in Linux in order to add a custom favicon to each bookmark in my bookmarks menu that did not already have a favicon. The procedure I used is given below.

1. Launch Firefox and enter ‘about:support’ (without the quotes) in the address bar.

2. Click on ‘Profile Directory’ > ‘Open Directory’ (which, in my case, is the directory /home/fitzcarraldo/.mozilla/firefox/l7nt0jx2.default).

3. Create the sub-directory ‘chrome‘.

4. Open the new directory’s folder.

5. Create the file ‘userChrome.css‘ in the new directory.

6. Open the file userChrome.css with a text editor and paste the following CSS code into it:

@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");

.bookmark-item[label="<bookmark name>"] image {
    width:0!important;
    height:0!important;
    padding: 0 0 16px 16px !important;
    background:url(<base64 string>)!important; 
}

7. Make the following changes to the above code:

7.1 Replace ‘<bookmark name>’ with the name of the bookmark as it appears in the bookmarks menu. You must supply a name, even if you do not want a name to appear.

7.2 Replace ‘<base64 string>’ with the base64-encoded string of the desired favicon, which you can obtain by uploading the 16×16 pixel image file to a website such as https://www.base64-image.de/.

Example

Below are the steps I took to create a favicon for the bookmark for Hotmail I have in Firefox:

1. I used a search engine to find an image of the Microsoft ‘flag’ logo. The image happened to be a 200×200 pixels PNG file. I downloaded it to my home directory and named it ‘Microsoft.png‘.

2. I loaded the image file into the GIMP, scaled it to 16×16 pixels and exported it as Microsoft.png to overwrite the original downloaded file.

3. I viewed the Web page https://www.base64-image.de/ in a Web browser and clicked on the button ‘OR CLICK HERE’ to upload my image file Microsoft.png to that site. Then I clicked on the button ‘</> show code’, selected and copied the text displayed underneath ‘For use as CSS background:’ that looked like this:

url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAOVBMVEXxURv7vAmAzCgAre/////xTxf8wB8csfD7wCXyXjDyWyuHzzaJ0Dohs/DyWSj0Zz2Q00b8xDMxt/HxkgKEAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4goMEQsUc/RzwQAAAB5JREFUGNNjYIAAViYoYKCPACsUwAWYoYARCgZIAADfYwHMYVta3QAAAABJRU5ErkJggg==')

4. I created the directory ~/.mozilla/firefox/l7nt0jx2.default/chrome and the file userChrome.css containing the following:

@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");

.bookmark-item[label="Hotmail"] image {
    width:0!important;
    height:0!important;
    padding: 0 0 16px 16px !important;
    background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAOVBMVEXxURv7vAmAzCgAre/////xTxf8wB8csfD7wCXyXjDyWyuHzzaJ0Dohs/DyWSj0Zz2Q00b8xDMxt/HxkgKEAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4goMEQsUc/RzwQAAAB5JREFUGNNjYIAAViYoYKCPACsUwAWYoYARCgZIAADfYwHMYVta3QAAAABJRU5ErkJggg==')!important; 
}

5. I restarted Firefox, and my custom favicon is now visible for the Hotmail entry in the Bookmarks Menu. I then deleted the file ~/Microsoft.png as it is no longer required.

6. I also wanted to create a custom favicon for another bookmark I have, the Web site of a Brazilian newspaper Correio Popular. As I was unable to find an image that would be suitable for a favicon, I created one myself (16×16 pixels) using the GIMP, and exported it as the file ‘~/Correio Popular.png‘.

7. I followed the same procedure to encode the image file as a Base64 image, and I added another entry to the file ~/.mozilla/firefox/l7nt0jx2.default/chrome/userChrome.css, which now contains the following:

@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");

.bookmark-item[label="Hotmail"] image {
    width:0!important;
    height:0!important;
    padding: 0 0 16px 16px !important;
    background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAOVBMVEXxURv7vAmAzCgAre/////xTxf8wB8csfD7wCXyXjDyWyuHzzaJ0Dohs/DyWSj0Zz2Q00b8xDMxt/HxkgKEAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4goMEQsUc/RzwQAAAB5JREFUGNNjYIAAViYoYKCPACsUwAWYoYARCgZIAADfYwHMYVta3QAAAABJRU5ErkJggg==')!important; 
}

.bookmark-item[label="Correio Popular"] image {
    width:0!important;
    height:0!important;
    padding: 0 0 16px 16px !important;
    background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4goMFzEqk7HMoQAAAQdJREFUKM/NkrGKg0AURd+EwSkMBPwLSxlI5dR+haSxFE0T7KxtghCwtfNH7FLZpkkXgvMDophwtzArYUMWUizsad7j8i7cC48BoE9Y0If8vYFPo+u6MAxXq9VyubxcLoyxsiz3+31VVUqp6/WqlIqiiIgIAADO+el0wje73W5a5oP1el0UBQACUBSF67p4ou97ALfbbTakaer7PoAFER2PR8dxnoMKIX5Er+taSvnoMI4j5/xdy+12ez6fpZRxHD86ZFnmed7vkWYIwDAMRKS1ntUkSQDc7/dXAyciwzC01kEQ2LZtmmbbtk3TENHhcBBC5Hm+2Wwsy5oSsne/BIAx9qqz//d8XzCj1kv+0nVJAAAAAElFTkSuQmCC')!important; 
}

8. For any other bookmarks that do not have a favicon, I will just repeat the procedure to add further entries to the file ~/.mozilla/firefox/l7nt0jx2.default/chrome/userChrome.css. It is not as easy as using an add-on, but, until someone creates one, the process described above at least allows me to fill those annoying favicon gaps in the Firefox bookmark menus on my machines.