About the top panel
The panel that appears at the uppermost area of the viewport is drawn by
lemonbar
. This is a beautifully simple tool. On the face of it, all
it does is place an empty bar at either the top (default) or bottom of
the screen, while offering a syntax for formatting any output it may
display. It is up to the user to add content to it.
This is where my melonpanel
comes into play. It is a shell script
that fetches and parses some useful information about the system and the
running session, and lays it on the bar. Each snippet of info is
internally referred to as a “module” and has its own dedicated logic
inside the script.
The modules are the following:
- BSPWM report about the workspaces, nodes, their flags and state (see next section about it).
- Battery status and current capacity.
- Core temperature.
- Speaker volume strength and status.
- Keyboard indicators for alternate layout and caps lock.
- Date and time.
This is what a module looks like:
# Core temperature.
_temperature() {
command -v acpi > /dev/null || return 1
local therm_label therm_status
therm_label='T:'
therm_status="$(acpi -t | awk -F '[[:space:]]+|,' '{ print $5 }')"
therm_status="${therm_status:0:2}"
# Up to 59 degrees celcius keep text colour same as default. 60-79
# turn the colour red on normal background. Else turn the whole
# indicator red.
case "$therm_status" in
[12345][0-9])
echo "$therm_label ${therm_status}°C"
;;
[67][0-9])
echo "$therm_label %{F$color1}${therm_status}°C%{F-}"
;;
*)
echo "%{F$background}%{B$color1} $therm_label ${therm_status}°C %{B-}%{F-}"
;;
esac
}
How the modules are placed on the panel
All modules will grab some piece of text and clean it up so that it
looks nice on the panel. However, each individual module does not
output directly to the named pipe where the data is read from.
Instead, all modules are called from _modules()
, which I need to
explain a bit:
_modules() {
while true; do
echo "B" "$(_battery)"
echo "T" "$(_temperature)"
echo "D" "$(_datetime)"
echo "K" "$(_keyboard)"
echo "V" "$(_volume)"
sleep 1s
done
}
You will notice that each individual item echoes a majuscule and then
the output of the module it references. These capital letters are
important because they demarcate each set of data in the named pipe,
making it possible to put the right thing in the right place. We see
this in practice at _melonpanel()
, specifically this part:
while read -r line ; do
case $line in
B*)
# battery status
bat="${line#?}"
;;
T*)
# temperature
therm="${line#?}"
;;
D*)
# current date and time
date="${line#?}"
;;
K*)
# keyboard layout (en or gr)
key="${line#?}"
;;
V*)
# volume level
vol="${line#?}"
;;
What this does is identify the part that contains the data of each module and assign a variable to it. The variables are then placed on the panel with the following:
_panel_layout() {
echo "%{l}$wm%{r}$key $bat $therm $vol $date "
}
Focus on the content of the echo
. The syntax %{l}
places things on
the left, while %{r}
aligns them to the right (this notation is
provided by lemonbar
—see its manpage).
I believe this pretty much covers the essentials of how melonpanel
is
designed. As with all my scripts, this too is heavily documented. So
do read it. That granted, I admit that lemonbar
is not the most
user-friendly, point-and-click program out there. But hey, neither is
BSPWM, Xterm, Tmux, Vim, etc.
The BSPWM module
On the left side of the panel lies the set of indicators that report on
the status of the window manager (based on the output of the command
bspc subscribe report
). This is what you see when starting the
session (note that I have taken care to use the appropriate spacing, so
that all typographic elements are evenly spread out):
[1] *
The numbers correspond to the names of the available desktops. Because I have implemented dynamic desktops (see chapter about the advanced features of my BSPWM), there is only one desktop on the panel. If you navigate to desktop number two, the module will be like this, if desktop 1 is empty:
[2] *
If desktop 1 is occupied, the module will be:
1^ [2] *
The desktop inside square brackets (and also drawn with a bold font) is the current one, while the caret sign denotes an occupied desktop.
Next to the desktop numbers there is at least one asterisk. If the desktop contains windows, then the asterisks are two:
- The first asterisk always indicates the layout of the desktop. If the
view is set to monocle, then the letter
M
will take the place of the asterisk. The layout cycles between tiled and monocle, but because the former is what we normally use, I have opted to hide theT
behind the asterisk and only display theM
. - The second asterisk contains information about the active window’s
flags. The flags I define in my
sxhkdrc_bspc
are: Sticky, Private, Locked, Marked (seeman bspc
for their meaning). When a flag for the current node is active, its initial letter is displayed on the panel. More than one flags can be activated at once.
If all indicators are toggled on at once, you will see something like this:
[1] 2^ * SPLM
Urgent and unfocused desktops are denoted by the column sign and are coloured red:
[1] 2# * *
On multi-head setups (e.g. dual monitor), the BSPWM report will divide desktops and their corresponding indicators per monitor. Combined with the above, we get the following:
[1] 2^ * L 4- 5# 6^ M SP
Notice how the indicators that display the *
(asterisk) are visible
for each set of desktops. Also look at the use of another typographic
marker next to desktop 4: the hyphen is for showing the focused
desktop on the unfocused monitor. The letter M
in this case concerns
desktop 4. Same with the node flags S
and P
. While L
applies to
the focused node in desktop 1 and the asterisk next to it informs us
that the layout is the default, i.e. tiled.
I believe all this will become easier to grasp once you start using the
system. For the record, this design bears close resemblance to the
status line of my tmux
setup.
Panel transparency
By default, the panel is opaque, though I have made it fairly trivial to
add a transparency effect to its background. The following is an
excerpt from the relevant melonpanel
section:
_melonpanel < "$melonpanel_fifo" | lemonbar -u 1 -p -g "x${melonpanel_height}" \
-F "$foreground" -B "#ff${background:1}" -f "$fontmain" -f "$fontbold" -n "Melonpanel" &
Take a closer look at the segment of the command that controls the
background colour: -B "#ff${background:1}"
. I have designed it so
that you can tweak its alpha value, which is governed by the ff
part.
This is hexadecimal notation and means that the alpha channel is set to
full, which translates to complete opacity. 00
is the opposite.
Try replacing ff
with aa
to get some subtle transparency, or with
55
for a more pronounced effect. Possible values for each digit are:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f. A running compositor is
required to enable transparency effects (I use compton
as already
mentioned in previous chapters).
As a rule of thumb, light themes will require a greater adjustment than dark themes to create a noticeable see-through style. The choice of wallpaper will also affect your perception of it.
For changes to be applied, reload the panel with the key chord chain
super + e ; p
(as explained in the chapter about the basics of my
BSPWM). Otherwise, you can always just use tempusmenu
to switch to
another Tempus theme (as discussed in the chapter about my themes), thus
forcing a panel reload.
Known issues
Sometimes, seemingly at random, the panel will not be hidden when
entering a window’s full screen view. The less-than-ideal workaround is
to reload melonpanel
with the key chord chain super + e ; p
. This
seems to be an upstream bug.
Another thing to bear in mind is that upstream lemonbar
does not
support proportional or outline fonts (e.g. the “DejaVu” family). It
can only display fixed-size, else bitmap, typefaces such as “Terminus”.
If you have followed the instructions in the chapter about installing
the core packages, you will have xfonts-terminus
available on your
system. This is an optional dependency, as the panel will fall back to
the fixed
typeface which comes pre-installed with Debian. I just
think that Terminus is more consistent and is better suited for such
a UI task (see ANNEX below for Lemonbar with proportional fonts).
Finally, you may notice that pgrep melonpanel
always lists two running
processes. This is because it is running _modules()
(mentioned above)
as well as bspc subscribe report
that displays desktop information and
the like. The report needs to be its own process because it has its own
synchronicity, controlled by the window manager itself (please let me
know if there is a way of merging every modules functionality into
a single process).
ANNEX for lemonbar-xft
I maintain a personal fork of lemonbar
with support for Xft (the
fontconfig library). This basically means running the panel using
proportional/outline fonts.
- I have a video where I talk about my fork.
- I also provide information on how I forked lemonbar-xft.
- And here is how to compile Lemonbar Xft on Debian 10 Buster.
I will not provide any further information herein. I do not encourage you to compile stuff from random sources or to create what is known as a “FrankenDebian”. I use this fork as part of my own system and am prepared to deal with any possible breakage. If you are not or do not trust my fork (you should not trust any random source), then stick with the package provided by Debian: it includes the upstream code that only uses bitmap fonts.