How to setup FreeBSD with a riced desktop - part 3 - i3

Published on 2020-01-24. Modified on 2022-04-14.

In this part we're going to install i3 and rice it bit. You can look further down in the tutorial at the screenshots in order to determine if you like the results.

Table of contents

Introduction

i3 is a tiling window manager written in C. It supports tiling, stacking, and tabbing layouts, which it handles dynamically. It uses a plain text file for configuration. i3 uses a control system very similar to vi. By default, window focus is controlled by the Mod (Alt key or Win key) plus the right hand home row keys J, K and L. Window movement is controlled by the addition of the Shift key. However, as everything is customizable, you can change that to anything you like.

I was recommended i3 during a chat with two friends about different GNU/Linux desktop solutions. The person who recommending i3 to me promised that it would increase my productivity and that I would love it.

I didn't, I actually hated it at first, and I didn't get why anyone would use a tilling window manager. I found the experience painful and I almost quit before I had even started. However, I knew that my friend, who was the same guy who originally introduced me to GNU/Linux back in 1998, also was a very skillful GNU/Linux programmer and system administrator, and I knew from experience, that his advice usually had merit.

In the beginning I struggled to memorize the different key combinations and kept reaching out for my mouse. While i3 does support the mouse, and you can switch application by clicking, you're not supposed to use it except within the applications themselves.

As I progressed I finally got it! After the "aha moment" I could not believe how I could have done without a tilling window manager before. As time progressed further and i3 became second nature to me, using other "normal" window managers and desktops has become annoying. Whenever I sit in front of someone else's computer in order to help with something, I cannot believe how unproductive it feels. I believe the main reason for this is that with a tilling window manager like i3 you use keyboard shortcuts and combinations for everything, and while you can setup keyboard shortcuts and combinations for other window managers and desktops as well, the control a tilling window manager provides is just so much better.

As mentioned in the first part of this tutorial I have tried out other tilling window managers since then, like dwm, Ion and Xmonad, but I prefer i3.

Dwm is pretty nice too, but I find it annoying that you need to use patches in order to customize it. Dwm has no configuration files and configuration is done in the source code, and every time it is upgraded you have to make sure the patches you use wont mess up the source code.

i3 is not as fast as Dwm, but it is still very fast by itself compared to just about everything else. It is very easy to customize, and it is highly productive to use.

Installation

I prefer to install i3-gaps which is a fork of the original i3 as it provides a few additional features such as gaps between windows. Gaps are not needed at all, but it just looks a little bit nicer, especially if you also add a wallpaper.

FreeBSD has both i3 and i3-gaps in the package repositories.

Besides from i3-gaps I also install a couple of other applications that I use in combination with i3.

$ doas pkg install i3-gaps i3lock i3status conky dmenu xterm gnome-screenshot nitrogen

i3lock is a small screen locking application. I use Mod+CTRL+l to lock my keyboard whenever I go to the kitchen for a cup of tea because sometimes my cat likes to run across my desk and step on all the keys on the keyboard :) When I get back to the keyboard I just type in my password and the screen is unlocked. i3lock supports a background wallpaper, so you can change the wallpaper based upon whether the screen is locked or not.

i3status is a small application for i3 that generates a status bar. I combine i3status with Conky in order to get some useful output. Some people prefer to also use font based text icons in the status bar, but I feel they clutter up the status bar and as such I much prefer to keep it more simple.

The dmenu application is from the Dwm window manager. It is a dynamic menu for X that is able to manage a large numbers of user-defined menu items very fast.

Some people prefer more complex menu managers, such as Rofi. I have used Rofi, but prefer the simplicity and speed of dmenu.

I also like to use the screenshot application from GNOME. Besides from a single package dependency on FreeBSD, it is a stand alone application that can be used without pulling in tons of GNOME stuff.

Nitrogen is a lightweight desktop background wallpaper browser and setter for X Window.

Last, but not least, xterm is my favorite terminal emulator for X. I have tried out all the other terminal emulators as well, including Alacritty, Eterm, rxvt, urxvt and st from the suckless project.

In the end I settled on Xterm as it not only has wide support and is installable on just about any system, it is also very customizable and fast.

If you come from one of the heavier desktops and are used to something like the GNOME terminal or Konsole from KDE, Xterm requires some getting used too. You cannot right click in Xterm and get a menu with different shortcuts or options, but you don't need any of that once you understand how Xterm works. In the setup below I also provide the customization I use for Xterm, but you can of course use any terminal emulator in combination with i3.

As with Xfce we need to install Xorg before we can use i3:

$ doas pkg install xorg

Remember to also install the driver for your graphics card. Take a look at the FreeBSD wiki to determine what you need.

I'm using a Broadwell processors so I install the drm-kmod module:

$ doas pkg install drm-kmod

Then in order to enable the module:

# sysrc kld_list="i915kms"

Ensure that all users requiring graphics are members of the "video" group.

# pw groupmod video -M USERNAME

I also want to be able to utilize the GPU when I am watching video with `mpv`, so I am going to install the libva-intel-media-driver. On an NVIDIA GPU you need the relevant NVIDIA driver.

# pkg install libva-intel-media-driver mpv

Then when you use mpv on Intel, you can run it with:

$ mpv --vo=gpu --hwdec=vaapi video.mkv

Or if you're on NVIDIA:

$ mpv --vo=gpu --hwdec=cuda video.mkv

I then reboot the machine here.

Then we need to create the .xinitrc file so we can use startx. Insert the following:

exec i3

With this setup we can now login to the machine and simply type x, which is an alias to the startx command that will run the startxfce4 command.

If you prefer, you can install a graphical login manager.

Don't start X just yet.

Setup

If you start X before setting up i3 it will generate a default setup for you and you can choose between using the Alt key or the Win key as Mod. However, as I already have a working setup, I prefer to use that before I start X.

First create the following directory in your home directory:

$ mkdir -p .config/i3

Then create the file config and put that into the newly created directory. The resulting path for the file is ~./config/i3/config. This is what I have got in my config file (everything is commented):

# i3 config file (v4)

# I prefer to use the Win key as the mod key.
# Arch Linux.
#set $mod Mod4
# FreeBSD.
set $mod Mod1

# Default font for i3.
font pango:DejaVu Sans Mono 8
#font pango:Monospace 10

# Use Mouse+$mod to drag floating windows to their wanted position.
floating_modifier $mod

# Disable focus following the mouse.
focus_follows_mouse no

# Kill focused window.
bindsym $mod+Shift+q kill

# Chance focus.
bindsym $mod+h focus left
bindsym $mod+j focus down
bindsym $mod+k focus up
bindsym $mod+l focus right

# Alternatively use arrow keys.
bindsym $mod+Left focus left
bindsym $mod+Down focus down
bindsym $mod+Up focus up
bindsym $mod+Right focus right

# Move focused window.
bindsym $mod+Shift+h move left
bindsym $mod+Shift+j move down
bindsym $mod+Shift+k move up
bindsym $mod+Shift+l move right

# Alternatively use arrow keys.
bindsym $mod+Shift+Left move left
bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right

# Split in horizontal orientation.
bindsym $mod+t split h

# Split in vertical orientation.
bindsym $mod+v split v

# Enter fullscreen mode for the focused container.
bindsym $mod+f fullscreen toggle

# Change container layout (stacked, tabbed, toggle split).
bindsym $mod+s layout stacking
bindsym $mod+w layout tabbed
bindsym $mod+e layout toggle split

# Toggle tiling / floating.
bindsym $mod+Shift+space floating toggle

# Change focus between tiling / floating windows.
bindsym $mod+space focus mode_toggle

# Focus the parent container.
#bindsym $mod+a focus parent

# Focus the child container.
#bindsym $mod+d focus child

# Switch to workspace.
bindsym $mod+1 workspace 1
bindsym $mod+2 workspace 2
bindsym $mod+3 workspace 3
bindsym $mod+4 workspace 4
bindsym $mod+5 workspace 5
bindsym $mod+6 workspace 6
bindsym $mod+7 workspace 7
bindsym $mod+8 workspace 8
bindsym $mod+9 workspace 9
bindsym $mod+0 workspace 10

# Move focused container to workspace.
bindsym $mod+Shift+1 move container to workspace 1
bindsym $mod+Shift+2 move container to workspace 2
bindsym $mod+Shift+3 move container to workspace 3
bindsym $mod+Shift+4 move container to workspace 4
bindsym $mod+Shift+5 move container to workspace 5
bindsym $mod+Shift+6 move container to workspace 6
bindsym $mod+Shift+7 move container to workspace 7
bindsym $mod+Shift+8 move container to workspace 8
bindsym $mod+Shift+9 move container to workspace 9
bindsym $mod+Shift+0 move container to workspace 10

# This only works for i3-gaps.
gaps inner 20
gaps outer 5

# Disable title bars.
for_window [class="^.*"] border pixel 1

# Key combination for dmenu.
bindsym $mod+d exec dmenu_run

# If you prefer Rofi to dmenu, you can comment out the above and use this
# instead. Remember to install the Rofi package: 'doas pkg install rofi'.
#bindsym $mod+d exec "rofi -combi-modi window,drun -show combi -modi combi"

# Key combination for some of my favorite applications.
bindsym $mod+Return exec "xterm"
bindsym $mod+Shift+m exec "claws-mail"
bindsym $mod+Shift+g exec "gimp"
bindsym $mod+Shift+f exec "firefox"
bindsym $mod+Shift+t exec "hexchat"
bindsym $mod+Shift+z exec "filezilla"

# Map the print key to gnome-screenshot.
bindsym Print exec "gnome-screenshot -i"

# Some applications needs to be floating. mpv is one of them.
for_window [class="mpv"] floating enable

# Let's try to get most pop-up windows floating.
for_window [window_role="pop-up"] floating enable
for_window [window_role="bubble"] floating enable
for_window [window_role="task_dialog"] floating enable
for_window [window_role="Preferences"] floating enable
for_window [window_type="dialog"] floating enable
for_window [window_type="menu"] floating enable

# Screen lock. See 'man i3lock' for information about usage.
bindsym $mod+Control+l exec "i3lock -t -i ~/.lock1.png --color=000000"

# Jump to the latest "urgent" window.
bindsym $mod+u [urgent=latest] focus

# Reload the configuration file.
bindsym $mod+Shift+r reload

# Restart i3 inplace (preserves your layout/session, can be used to upgrade i3).
bindsym $mod+Shift+e restart

# Exit i3 (logs you out of your X session).
# In my case I don't want a warning or anything, so be careful about pressing
# this combination as it kills X. Also be sure to lock down all applications
# before usage.
bindsym $mod+Shift+x exec i3-msg exit

# If you like a warning that needs to be confirmed with the mouse, you can use
# the following instead.
#bindsym $mod+Shift+x exec "i3-nagbar -t warning -m 'Do you really want to end your X session.' -b 'Yes, exit i3' 'i3-msg exit'"

# Resize window (you can also use the mouse for that).
mode "resize" {
        # These bindings trigger as soon as you enter the resize mode.
        bindsym h resize shrink width 10 px or 10 ppt
        bindsym j resize grow height 10 px or 10 ppt
        bindsym k resize shrink height 10 px or 10 ppt
        bindsym l resize grow width 10 px or 10 ppt

        # Same bindings, but for the arrow keys.
        bindsym Left resize shrink width 10 px or 10 ppt
        bindsym Down resize grow height 10 px or 10 ppt
        bindsym Up resize shrink height 10 px or 10 ppt
        bindsym Right resize grow width 10 px or 10 ppt

        # Back to normal: Enter or Escape.
        bindsym Return mode "default"
        bindsym Escape mode "default"
}

# Resize windows.
bindsym $mod+r mode "resize"

bar {
    colors {
        background #1e1e1e
        statusline #ffffff
        separator  #1e1e1e
        focused_workspace  #008fff #007fff #ffffff
        active_workspace   #333333 #5f676a #ffffff
        inactive_workspace #333333 #222222 #888888
        urgent_workspace   #aa0000 #990000 #ffffff
    }
    position top
    status_command ~/.config/i3/conky-i3bar.sh
}

## Autostart applicatons ##

# Let's get our wallpaper.
# You can run nitrogen from the console and set it up, afterwards use "--restore" to use it in i3.
exec --no-startup-id "nitrogen --restore"

# If you would like to be able to switch between keyboard layouts, this is the
# way to do it. As an example I am swithing between a Danish and an Arabic
# keyboard layout in this setup.
# You switch between layouts by pressing "left CTRL + right CTRL".
exec --no-startup-id "setxkbmap -layout dk,ara -option grp:ctrls_toggle"

This was the basic setup for i3. Let's setup Conky before we start X.

Conky

Conky is very configurable and it is able to monitor many system variables and resources. Other options exist, but I prefer to use Conky.

Add the file .conkyrc in your home folder and insert the following:

conky.config = {
    background = false,
    cpu_avg_samples = 2,
    no_buffers = true,
    out_to_console = true,
    out_to_x = false,
    own_window = false,
    update_interval = 1,
    short_units = true,
    total_run_times = 0
};

conky.text = [[

[
    {"full_text": "CPU: ${cpu cpu0}% ", "color":"\#cf6a4c"},
    {"full_text": " | ", "color":"\#555555"},
    {"full_text": "RAM: $mem","color":"\#cda869"},
    {"full_text": " | ", "color":"\#555555"},
    {"full_text": "LAN: ${addr em0}","color":"\#89b859"},
    {"full_text": " | ", "color":"\#555555"},
    {"full_text": "VPN: ${addr tun0}","color":"\#00aaaa"},
    {"full_text": " | ", "color":"\#555555"},
    {"full_text": "${exec hostname }", "color":"\#9b703f"},
    {"full_text": " | ", "color":"\#555555"},
    {"full_text": "UP: ${uptime_short} ", "color":"\#838184"},
    {"full_text": " | ", "color":"\#555555"},
    {"full_text": "${time %A %Y-%m-%d}", "color":"\#cccccc"},
    {"full_text": "${time %H:%M}", "color":"\#cccccc"}
],

]];

Then create an sh script called conky-i3bar.sh and place it in ~/.config/i3/ with the following contents:

#!/bin/sh

# Send the header so that i3bar knows we want to use JSON:
echo '{"version":1}'

# Begin the endless array.
echo '['

# We send an empty first array of blocks to make the loop simpler:
echo '[],'

# Now send blocks with information forever:
exec conky -c ~/.conkyrc

Make the script executable:

$ chmod +x ~/.config/i3/conky-i3bar.sh

Now we need to setup Xterm.

xterm

There exist a ton of user provided script for Xterm on the Internet.

Create the file .Xresources in your home directory and insert the following:

xterm*faceName: "DejaVu Sans Mono"
xterm*faceSize: 12
xterm*renderFont: true
! Dynamically change font size with CTRL+SHIFT+PageUp/PageDown
xterm*faceSize1: 12
xterm*faceSize2: 14
xterm*faceSize3: 16
xterm*faceSize4: 18
xterm*faceSize5: 20
xterm*faceSize6: 22
xterm*utf8: 1
xterm*termName: xterm-256color
xterm*borderWidth: 0
xterm*autohint: true
xterm*backarrowKey: false
xterm*bellIsUrgent: false
xterm*cursorBlink: false
xterm*ScrollKey: true
! Fix ALT key (check in mc with Alt+h)
xterm*metaSendsEscape: true
xterm*eightBitInput: false
xterm*ttyModes: erase ^?
xterm*fastScroll: true

! I like a lot of scrollback.
xterm*saveLines: 100000

! Use CLIPBOARD by default.
xterm*selectToClipboard: true
! Hack xterm to add selection to both PRIMARY and CLIPBOARD.
<Btn1Up>: select-end(PRIMARY, CLIPBOARD, CUT_BUFFER0)

! xterm defines a whole suite of "actions" for manipulating the terminal e.g.
! copy-selection(), hard-reset(), scroll-back(), etc. These actions can be
! mapped to mouse/key combinations using the translations resource.
! These are the xterm.VT100.translations.
! Normally, selected text is stored in PRIMARY, to be pasted with Shift+Insert
! or by using the middle mouse button. With these settings you can use
! CTRL+SHIFT+v/c and you can make Xterm copy to clipboard so that you can use
! CTRL+v in GUI applications.
! Also we have to make sure these do not conflict with Vim. I use ALT+j/k and
! CTRL+SHIFT+j/k in Vim, so here it is SHIFT+ALT+j/k.
! The translations below only work for VT100.
xterm*VT100.translations: #override \n\
    Shift Alt J: scroll-forw(1, halfpage) \n\
    Shift Alt K: scroll-back(1, halfpage) \n\
    Ctrl +: larger-vt-font() \n\
    Ctrl -: smaller-vt-font() \n\
    Shift Ctrl C: copy-selection(CLIPBOARD) \n\
    Shift Ctrl V: insert-selection(CLIPBOARD) \n\
    BackSpace: string(0x7f) \n\
    Delete: string(0x1b) string("[3~")

! Theme.
! https://github.com/logico-dev/Xresources-themes
#include ".dotfiles/xresource-themes/ubuntu.Xresources"

If you have a long text in the terminal you can also use SHIFT+PageUp to scroll up to the beginning of the text, then left click with the mouse at the very beginning of the text, then go back down to the end of the text and right click at the end of the text. That way the entire text gets copied.

Text that is marked by the mouse is automatically copied.

When CTRL+v isn't working for insertion in GUI's and elsewhere, you can use CTRL+SHIFT+v instead.

Now you can start X by typing x, using the alias from the first part of the tutorial.

If you have done everything right, you should get the following result:

i3 without any apps opened

Nitrogen

In order to make the background of the desktop a bit more appealing I like to install a wallpaper. Because we're using i3-gaps the wallpaper will also be visible between the gaps of the opened applications.

Start by downloading a wallpaper you like and place it in a directory in your home directory. I prefer something like .wallpaper.

Then open up Nitrogen by pressing CTRL+d, to open dmenu, and then start typing "nitrogen", press the "Enter" key when it is selected.

When Nitrogen has opened up, click Preferences and then click + Add.

If you have chosen a hidden directory for your wallpapers you need to press CTRL+h to make it visible. Choose the directory and click on OK. Then click on the wallpaper and click on Apply.

Now your desktop should look something like this:

i3 without any apps opened

And with some applications opened:

i3 with apps opened

Please note that I'm running this on a virtual machine with a smaller screen just for this tutorial, so I cannot fit that many applications on the same screen.

Final comments

One of the nice features with the above setup of i3 is that you can open up multiple windows. If you press Mod+2, the second window is going to open up, and you can have running applications on that too.

i3's workflow is so efficient, it has all but replaced my multi-monitor setup.

For information on how to get the most out of i3 take a look at the docs. Also you can find several pretty good tutorials on YouTube on how to both "rice" and use i3.

That was it. I hope that you have found this three part tutorial useful :)