Install i3 Windows Manager on Ubuntu 24.04

|
Last Updated:
|
|

Welcome to our tutorial on how to install i3 windows manager on Ubuntu 24.04. i3 is a tiling window manager for X11. “A tiling window manager is a window manager with an organization of the screen into mutually non-overlapping frames, as opposed to the more popular approach of coordinate-based stacking of overlapping objects (windows) that tries to fully emulate the desktop metaphor.”

Installing i3 Windows Manager on Ubuntu 24.04

Run System Update

To begin with, run system package update.

sudo apt update

Install i3 Windows Manager

i3 windows manager can be installed via the i3 package which is available on the default Ubuntu 24.04 repos.

sudo apt show i3
Package: i3
Version: 4.23-1
Priority: optional
Section: universe/x11
Source: i3-wm
Origin: Ubuntu
Maintainer: Ubuntu Developers 
Original-Maintainer: Debian i3 maintainers 
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 10.2 kB
Depends: i3-wm (= 4.23-1)
Recommends: i3lock, suckless-tools, dunst
Homepage: https://i3wm.org/
Download-Size: 2,042 B
APT-Sources: http://de.archive.ubuntu.com/ubuntu noble/universe amd64 Packages
Description: metapackage (i3 window manager, screen locker, menu, statusbar)
 This metapackage installs the i3 window manager (i3-wm), the i3lock screen
 locker, i3status (for system information) and suckless-tools (for dmenu).
 These are all the tools you need to use the i3 window manager efficiently.

There are other tools that are needed to use the i3 window manager efficiently. These include;

  • i3 window manager: The i3-wm itself
  • i3lock screen locker
  • i3status for system information
  • suckless-tools for dmenu

These packages are installed along with the i3 meta package.

The default Ubuntu 24.04 repositories provides the latest release version of i3-wm. You can install it by running the command below;

sudo apt install i3

Configuring i3 Windows Manager on Ubuntu 24.04

Once the installation is done, you can now proceed to configure i3-wm on Ubuntu 24.04.

Login with i3 WM Session

First, log out of your system and log in again. While logging in, be sure to select i3 session at your login screen.

So, click the username to get the password prompt. You will then see the login settings gear icon.

Generate or use Default i3 WM Configuration

Upon successfully logging in, you are then prompted on whether to:

  • auto-generate an i3-wm configuration file, ~/.config/i3/config or
  • simply use the default configuration file.

In this setup, we will go with the first option to auto generate the i3-wm configuration file. We will later modify it to suit our needs. Therefore, press ENTER to continue.

Define i3 WM Modifier Key

Next, you need to define the i3-wm modifier key ($mod). You have two options here: you can use the Windows logo key or the Alt key.

In this setup, we will use the popular $mod key, the Windows logo key as our i3-wm modifier, and is selected by default. Use the arrow up or down keys to select the $mod keys.

Write the changes by pressing ENTER.

And you should now be welcomed by black screen with some status bar at the bottom that resembles the one shown in the screenshot below;

i3 wm default status bar

Basic Usage of i3

Now that i3WM is installed with the basic configuration setup, there are a few key combinations that can be used to perform some basic tasks;

Note that $mod represents the modifier key you selected. Either Alt or Win key. It is Win key on our setup.

  • Open a terminal: $mod + ENTER.
  • Launching system applications via the dmenu: $mod + d. This opens up a menu at the top of the screen where you can put keywords to search for specific app.
  • Enter a fullscreen mode on and off: $mod + f.
  • Closing an application window; $mod + Shift + q
  • Restarting i3: $mod + Shift + r.
  • Exiting i3 windows manager: $mod + Shift + e.
  • Opening terminal with default config: $mod + ENTER.

Customizing i3 on Ubuntu 24.04

Next, we want to make i3 appealing and easy to use. You can customize i3-wm by modifying the ~/.config/i3/config file.

Below is the default configs;

# This file has been auto-generated by i3-config-wizard(1).
# It will not be overwritten, so edit it as you like.
#
# Should you change your keyboard layout some time, delete
# this file and re-run i3-config-wizard(1).
#

# i3 config file (v4)
#
# Please see https://i3wm.org/docs/userguide.html for a complete reference!

set $mod Mod4

# Font for window titles. Will also be used by the bar unless a different font
# is used in the bar {} block below.
font pango:monospace 8

# This font is widely installed, provides lots of unicode glyphs, right-to-left
# text rendering and scalability on retina/hidpi displays (thanks to pango).
#font pango:DejaVu Sans Mono 8

# Start XDG autostart .desktop files using dex. See also
# https://wiki.archlinux.org/index.php/XDG_Autostart
exec --no-startup-id dex --autostart --environment i3

# The combination of xss-lock, nm-applet and pactl is a popular choice, so
# they are included here as an example. Modify as you see fit.

# xss-lock grabs a logind suspend inhibit lock and will use i3lock to lock the
# screen before suspend. Use loginctl lock-session to lock your screen.
exec --no-startup-id xss-lock --transfer-sleep-lock -- i3lock --nofork

# NetworkManager is the most popular way to manage wireless networks on Linux,
# and nm-applet is a desktop environment-independent system tray GUI for it.
exec --no-startup-id nm-applet

# Use pactl to adjust volume in PulseAudio.
set $refresh_i3status killall -SIGUSR1 i3status
bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +10% && $refresh_i3status
bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -10% && $refresh_i3status
bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status
bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status

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

# move tiling windows via drag & drop by left-clicking into the title bar,
# or left-clicking anywhere into the window while holding the floating modifier.
tiling_drag modifier titlebar

# start a terminal
bindsym $mod+Return exec i3-sensible-terminal

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

# start dmenu (a program launcher)
bindsym $mod+d exec --no-startup-id dmenu_run
# A more modern dmenu replacement is rofi:
# bindcode $mod+40 exec "rofi -modi drun,run -show drun"
# There also is i3-dmenu-desktop which only displays applications shipping a
# .desktop file. It is a wrapper around dmenu, so you need that installed.
# bindcode $mod+40 exec --no-startup-id i3-dmenu-desktop

# change focus
bindsym $mod+j focus left
bindsym $mod+k focus down
bindsym $mod+l focus up
bindsym $mod+semicolon focus right

# alternatively, you can use the cursor 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+j move left
bindsym $mod+Shift+k move down
bindsym $mod+Shift+l move up
bindsym $mod+Shift+semicolon move right

# alternatively, you can use the cursor 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+h 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

# Define names for default workspaces for which we configure key bindings later on.
# We use variables to avoid repeating the names in multiple places.
set $ws1 "1"
set $ws2 "2"
set $ws3 "3"
set $ws4 "4"
set $ws5 "5"
set $ws6 "6"
set $ws7 "7"
set $ws8 "8"
set $ws9 "9"
set $ws10 "10"

# switch to workspace
bindsym $mod+1 workspace number $ws1
bindsym $mod+2 workspace number $ws2
bindsym $mod+3 workspace number $ws3
bindsym $mod+4 workspace number $ws4
bindsym $mod+5 workspace number $ws5
bindsym $mod+6 workspace number $ws6
bindsym $mod+7 workspace number $ws7
bindsym $mod+8 workspace number $ws8
bindsym $mod+9 workspace number $ws9
bindsym $mod+0 workspace number $ws10

# move focused container to workspace
bindsym $mod+Shift+1 move container to workspace number $ws1
bindsym $mod+Shift+2 move container to workspace number $ws2
bindsym $mod+Shift+3 move container to workspace number $ws3
bindsym $mod+Shift+4 move container to workspace number $ws4
bindsym $mod+Shift+5 move container to workspace number $ws5
bindsym $mod+Shift+6 move container to workspace number $ws6
bindsym $mod+Shift+7 move container to workspace number $ws7
bindsym $mod+Shift+8 move container to workspace number $ws8
bindsym $mod+Shift+9 move container to workspace number $ws9
bindsym $mod+Shift+0 move container to workspace number $ws10

# reload the configuration file
bindsym $mod+Shift+c reload
# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)
bindsym $mod+Shift+r restart
# exit i3 (logs you out of your X session)
bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will 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

        # Pressing left will shrink the window’s width.
        # Pressing right will grow the window’s width.
        # Pressing up will shrink the window’s height.
        # Pressing down will grow the window’s height.
        bindsym j resize shrink width 10 px or 10 ppt
        bindsym k resize grow height 10 px or 10 ppt
        bindsym l resize shrink height 10 px or 10 ppt
        bindsym semicolon 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 or $mod+r
        bindsym Return mode "default"
        bindsym Escape mode "default"
        bindsym $mod+r mode "default"
}

bindsym $mod+r mode "resize"

# Start i3bar to display a workspace bar (plus the system information i3status
# finds out, if available)
bar {
        status_command i3status
}

We have customized the configuration file and thus, below is our sample i3 wm configuration;

cat ~/.config/i3/config
# Please see http://i3wm.org/docs/userguide.html for a complete reference!
#

set_from_resource $darkred     color1  #000000
set_from_resource $red         color9  #000000
set_from_resource $darkgreen   color2  #000000
set_from_resource $green       color10 #000000
set_from_resource $darkyellow  color3  #000000
set_from_resource $yellow      color11 #000000
set_from_resource $darkblue    color4  #000000
set_from_resource $blue        color12 #000000
set_from_resource $darkmagenta color5  #000000
set_from_resource $magenta     color13 #000000
set_from_resource $darkcyan    color6  #000000
set_from_resource $cyan        color14 #000000
set_from_resource $darkwhite   color7  #000000
set_from_resource $white       color15 #000000

# Use custom colors for black
set $black       #282828
set $darkblack   #1d2021
set $transparent #00000000

set $mod Mod4
set $mod1 Mod1
set $terminator terminator


# Font for window titles. Will also be used by the bar unless a different font
# is used in the bar {} block below.
font pango:monospace 12

# This font is widely installed, provides lots of unicode glyphs, right-to-left
# text rendering and scalability on retina/hidpi displays (thanks to pango).

font pango:DejaVu Sans Mono 12
#font pango:Meslo LG L Regular Nerd Font Complete 15

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

# start a terminator by pressing Mod key + x or ENTER
bindsym $mod+Return exec $terminator
bindsym $mod+x exec $terminator

# Custom bindsyms
bindsym $mod+p exec ~/.config/i3/bin/logout
bindsym $mod+l exec i3lock -i /home/kifarunix/Pictures/linuxtux.png
bindsym $mod+c exec google-chrome
bindsym $mod+r mode "resize"
bindsym $mod+Shift+f exec /home/kifarunix/.config/i3/bin/rofifinder


# Enable Print Screen
#bindsym --release $mod+Print exec gnome-screenshot -i
bindsym --release $mod+Print exec shutter -s

# kill focused window
bindsym $mod+q kill

# start dmenu (a program launcher)
bindsym $mod+d exec --no-startup-id ~/.config/i3/bin/rofi_app_launcher


# change focus
bindsym $mod+j focus left
bindsym $mod+k focus down
# bindsym $mod+l focus up
bindsym $mod+semicolon focus right

# alternatively, you can use the cursor 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+j move left
bindsym $mod+Shift+k move down
bindsym $mod+Shift+l move up
bindsym $mod+Shift+semicolon move right

# alternatively, you can use the cursor 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+h 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+t 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+z focus child

# Workspace Variables
set $ws1 "1: "
#set $ws2 "2: "
set $ws2 "2: "
set $ws3 "3: "
set $ws4 "4: "
set $ws5 "5: "
set $ws6 "6:"
set $ws7 "7:"
set $ws8 "8: "
set $ws9 "9: "


# switch to workspace
bindsym $mod+1 workspace $ws1
bindsym $mod+2 workspace $ws2
bindsym $mod+3 workspace $ws3
bindsym $mod+4 workspace $ws4
bindsym $mod+5 workspace $ws5
bindsym $mod+6 workspace $ws6
bindsym $mod+7 workspace $ws7
bindsym $mod+8 workspace $ws8
bindsym $mod+9 workspace $ws9
bindsym $mod+0 workspace $ws10

# move focused container to workspace
bindsym $mod+Shift+1 move container to workspace $ws1
bindsym $mod+Shift+2 move container to workspace $ws2
bindsym $mod+Shift+3 move container to workspace $ws3
bindsym $mod+Shift+4 move container to workspace $ws4
bindsym $mod+Shift+5 move container to workspace $ws5
bindsym $mod+Shift+6 move container to workspace $ws6
bindsym $mod+Shift+7 move container to workspace $ws7
bindsym $mod+Shift+8 move container to workspace $ws8
bindsym $mod+Shift+9 move container to workspace $ws9
bindsym $mod+Shift+0 move container to workspace $ws10

# reload the configuration file
bindsym $mod+Shift+c reload
# restart i3 inplace
bindsym $mod+Shift+r restart
# exit i3 (logs you out of your X session)
bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will 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

        # Pressing left will shrink the window’s width.
        # Pressing right will grow the window’s width.
        # Pressing up will shrink the window’s height.
        # Pressing down will grow the window’s height.
        bindsym j resize shrink width 10 px or 10 ppt
        bindsym k resize grow height 10 px or 10 ppt
        bindsym l resize shrink height 10 px or 10 ppt
        bindsym semicolon 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 Up resize grow height 10 px or 10 ppt
        bindsym Down 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"
}
#
# Pulse Audio controls
# run pactl list sinks
#bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume 0 +5% #increase sound volume
#bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume 0 -5% #decrease sound volume#
#bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute 1 toggle # mute sound

# Amixer

bindsym XF86AudioRaiseVolume exec --no-startup-id amixer -D pulse sset Master 5%+ #increase sound volume
bindsym XF86AudioLowerVolume exec --no-startup-id amixer -D pulse sset Master 5%- #decrease sound volume#
bindsym XF86AudioMute exec --no-startup-id amixer -q set Master toggle # mute sound

# Sreen brightness controls
# enable passwordless sudo for ybacklight. echo "kifarunix ALL=NOPASSWD: /usr/bin/ybacklight" > /etc/sudoers.d/ybacklight
#bindsym XF86MonBrightnessUp exec sudo ybacklight -inc 5 # increase screen brightness
#bindsym XF86MonBrightnessDown exec sudo ybacklight -dec 5 # decrease screen brightness
bindsym XF86MonBrightnessDown exec --no-startup-id brightnessctl -q set 5%-
bindsym XF86MonBrightnessUp exec --no-startup-id brightnessctl -q set 5%+

# i3blocks
bar {
    status_command i3blocks
    position top
    font pango:Hack, FontAwesome 11

    colors {
        separator #081419
        background #253941
        #statusline #839496
        focused_workspace #fdf6e3 #6c71c4 #fdf6e3
        active_workspace #fdf6e3 #6c71c4 #fdf6e3
        inactive_workspace #002b36 #586e75 #002b36
        urgent_workspace #d33682 #d33682 #fdf6e3

        statusline         $white
        separator          $transparent
  }
}


set $m1 #808080 
set $m2 #FFF0E0

# Startup programs
exec --no-startup-id dunst 
exec_always compton &
exec --no-startup-id clipit & 
exec_always feh --bg-scale /home/kifarunix/Pictures/linux-wallpaper.png
exec_always --no-startup-id nm-applet


# Bind App to workspace
# Check class by using xprop command
assign [class="chromium"] $ws2
assign [class="Firefox"] $ws2
assign [class="Atom"] $ws3
assign [class="Foxit Reader"] $ws3
assign [class="Pcmanfm"] $ws4
assign [class="VirtualBox"] $ws5
assign [class="Virt-manager"] $ws5
assign [class="Skype"] $ws6
assign [class="mpv"] $ws9
assign [class="vlc"] $ws9
assign [class="Thunderbird"] $ws7
assign [class="(?i)libreoffice-startcenter"] $ws8
assign [class="(?i)soffice"] $ws8
assign [class="(?i)libreoffice"] $ws8


# Assign to certain workspace
assign [window_role="browser"] $ws2

# Press $mod+o followed by either f, s, l, m, v, k, d, t, Esc or Return {ENTER),
# to launch FoxiReader, Skype, lxappearance, thunderbird, VirtualBox,
# KVM Virt-manager, spectacle, pcmanfm file manager, 
# or return to the default mode, respectively.
set $mode_launcher Launcher
bindsym $mod+o mode "$mode_launcher"

mode "$mode_launcher" {
    bindsym f exec FoxitReader 
    bindsym s exec skypeforlinux
    bindsym l exec lxappearance  
    bindsym m exec thunderbird  
    bindsym v exec VirtualBox 
    bindsym k exec virt-manager 
    bindsym d exec spectacle 
    bindsym t exec "pcmanfm /home/kifarunix"

    bindsym Esc mode "default"
    bindsym Return mode "default"
}

# Shutdown, Reboot, Lock Screen, and Logout 

set $power_mode "power"
bindsym $mod+Shift+q      mode $power_mode
mode $power_mode {
    bindsym p         exec systemctl poweroff
    bindsym r         exec systemctl reboot 
    bindsym l         exec i3lock -i /home/kifarunix/Pictures/linuxtux.png, mode "default"
    bindsym q         exec --no-startup-id i3-msg exit, mode "default"
    bindsym h         exec sudo systemctl hibernate 
    bindsym s         exec sudo systemctl suspend
    bindsym Return    mode "default"
    bindsym Escape    mode "default"
}

# Floating windows
for_window [window_role="task_dialog|bubble|page-info|Preferences|pop-up"] floating enable
for_window [window_role="Open Files"] floating enable sticky
for_window [window_role="File Operation Progress"] floating enable sticky
for_window [class="qBittorrent" window_role="pop-up"] floating enable
for_window [window_type="dialog"] floating enable
for_window [window_type="menu"] floating enable

# Sticky window
for_window [instance="file_progress"]  sticky enable
for_window [class="info|Mate-color-select|gcolor2|timesup|QtPass|GtkFileChooserDialog"] sticky enable

# Focus window settings
no_focus [window_role="pop-up"]
focus_on_window_activation focus

There are some lines that are referencing my user’s home directory;

  • bindsym $mod+l exec i3lock -i /home/kifarunix/Pictures/linuxtux.png
  • bindsym $mod+Shift+f exec /home/kifarunix/.config/i3/bin/rofifinder
  • exec_always feh –bg-scale /home/kifarunix/Pictures/linux-wallpaper.png
  • bindsym t exec “pcmanfm /home/kifarunix
  • bindsym l exec i3lock -i /home/kifarunix/Pictures/linuxtux.png, mode “default”

Be sure to update them accordingly!

The above configuration should give you such a window (that is after all the configurations below is done);

general i3 wm

To use the above config, make a backup of the default configuration and paste the contents above into config file.

What is needed for the Customization above

Install Requires packages

A number of packages are requires for the above display and various shortcuts defined in the configuration file above;

sudo apt install feh \
	fonts-font-awesome \
	rofi \
	pulseaudio-utils \
	xbacklight \
	alsa-tools \
	clipit \
	gcc \
	git \
	terminator \
	locate \
	pcmanfm \
	acpi \
	libnotify-bin \
	htop \
	shutter \
	compton \
        i3blocks \
        plocate

Install brightnessctl for controlling the screen brightness if xbacklight doesn’t work;

cd /tmp;git clone https://github.com/Hummer12007/brightnessctl.git
cd brightnessctl;./configure;sudo make install

Install i3 Logout Script

As defined the i3 configuration above, log out script, which gives such an logout interface shown below upon pressing $mod+p key combination, is installed under, ~/.config/i3/bin/logout.

logout screen

Create the i3 binary scripts directory and install the logout script.

mkdir ~/.config/i3/bin/

cat > ~/.config/i3/bin/logout << 'EOL'
#!/usr/bin/env bash
# Manage logout with rofi
option=`echo -e "suspend\nlock screen\nlogout\nreboot\npoweroff\nKill user $USER" | rofi -width 600 -dmenu -p system:`
case $option in
    suspend)
        sudo  /usr/bin/systemctl syspend
        ;;
    'lock screen')
        i3lock -i /home/kifarunix/Pictures/linuxtux.png
        ;;
    logout)
        i3-nagbar -t warning -m 'Are you sure you  want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'
        ;;
    reboot)
        /usr/bin/systemctl reboot
        ;;
    poweroff)
        /usr/bin/systemctl poweroff
        ;;
    'kill user $USER')
        loginctl kill-user $USER
        ;;
esac
EOL

NB: The script is a modified version of the logout script provided on the Jmutai dotfiles github repository.Be sure to make the script executable;

chmod +x ~/.config/i3/bin/logout

Search and Locate Files using Rofi

The rofi can be used to search for and locate files and folders within your system. Below is the rofi finder script we use;

cat > ~/.config/i3/bin/rofifinder << 'EOL'
#!/bin/bash
xdg-open "$(locate -i / | rofi -threads 0 -width 100 -dmenu -i -p "Find")"
EOL
chmod +x ~/.config/i3/bin/rofifinder

The rofi finder can be launched, as per our config, by pressing $mod+Shift+f key combination. This is how it looks like;

Rofi finder Ubuntu 24.04

Note that the script uses locate command. There install it, if not already install, and update the plocate (mlocate) database;

sudo apt install plocate -y && sudo updatedb

Launching System Apps using Rofi

You can as well configure rofi to launch your system applications with i3-dmenu-desktop. Below is the script used in this guide to launch system apps;

cat > ~/.config/i3/bin/rofi_app_launcher << 'EOL'
#!/usr/bin/env bash
# Run rofi app launcher
i3-dmenu-desktop --dmenu="rofi -dmenu -i -p 'apps'"
EOL
chmod +x ~/.config/i3/bin/rofi_app_launcher

The i3 configuration for rofi app launcher is (define in the ~/.config/i3/config);

# start dmenu (a program launcher)
bindsym $mod+d exec --no-startup-id ~/.config/i3/bin/rofi_app_launcher

The shortcut for launching the rofi app launcher as per our config is, $mod+d. See sample launch menu screen;

rofi app launcher

To customize the rofi window, use rofi-theme-selector command.

rofi-theme-selector

Press ENTER to check each theme!

Other customizations;

Enable Print Screen using shutter

# Enable Print Screen
#bindsym --release $mod+Print exec gnome-screenshot -i
bindsym --release $mod+Print exec shutter -s

Killing a focussed windows;

# kill focused window
bindsym $mod+q kill

Changing Focus between different windows in a Workspace (see the respective key shortcuts);

# change focus
bindsym $mod+j focus left
bindsym $mod+k focus down
# bindsym $mod+l focus up
bindsym $mod+semicolon focus right

# alternatively, you can use the cursor 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+j move left
bindsym $mod+Shift+k move down
bindsym $mod+Shift+l move up
bindsym $mod+Shift+semicolon move right

# alternatively, you can use the cursor 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

Splitting a Window vertically ($mod+v) or horizontally ($mod+h);

# split in horizontal orientation
bindsym $mod+h split h

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

Set a window in a full screen mode ($mod+f);

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

Set a window to tiling or floating mode ($mod+Shift+space);

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

Changing the focus of the parent or child window;

# focus the parent container
bindsym $mod+a focus parent
# focus the child container
bindsym $mod+z focus child

Setting Icons for different Workspaces;

# Workspace Variables
set $ws1 "1: "
#set $ws2 "2: "
set $ws2 "2: "
set $ws3 "3: "
set $ws4 "4: "
set $ws5 "5: "
set $ws6 "6:"
set $ws7 "7:"
set $ws8 "8: "
i3workspace icons

You can search for these icons on FontAwesome icons page and copy the glyph of your preferred icon and paste between the colon (:) and closing quote (").

copy fontawesome icon

The icons used above are: linux, chrome, book, open folder, display, skype, envelop, windows and circle-play.

Note we also bind various applications to their respective workspaces;

# Bind App to workspace
# Check class by using xprop command
assign [class="chromium"] $ws2
assign [class="Firefox"] $ws2
assign [class="Atom"] $ws3
assign [class="Foxit Reader"] $ws3
assign [class="Pcmanfm"] $ws4
assign [class="VirtualBox"] $ws5
assign [class="Virt-manager"] $ws5
assign [class="Skype"] $ws6
assign [class="mpv"] $ws9
assign [class="vlc"] $ws9
assign [class="Thunderbird"] $ws7
assign [class="(?i)libreoffice-startcenter"] $ws8
assign [class="(?i)soffice"] $ws8
assign [class="(?i)libreoffice"] $ws8


# Assign to certain workspace
assign [window_role="browser"] $ws2

Set i3 Wallpaper

First off, let us set a wallpaper. i3 wallpaper can be set using feh, a light-weight, configurable and versatile image viewer. Run the command on terminal.

feh --bg-scale /path/to/wallpaper.jpg

This should automatically change your wallpaper. To ensure that the wallpaper is set always when you login to your i3 session, edit the ~/.config/i3/config and set the correct path to your wallpaper image;

exec_always feh --bg-scale /path/to/wallpaper.jpg

Configure i3blocks

i3blocks is an alternative to i3status. i3blocks is available on the default Ubuntu 24.04 repos. Install i3blocks and it by running the command below (if not already installed);

sudo apt install i3blocks

Next, configure i3 to use i3blocks instead of i3status by replacing the i3 bar {} section with the configs below;

# i3blocks
bar {
    status_command i3blocks
    position top
    font pango:Hack, FontAwesome 11

    colors {
        separator #081419
        background #253941
        #statusline #839496
        focused_workspace #fdf6e3 #6c71c4 #fdf6e3
        active_workspace #fdf6e3 #6c71c4 #fdf6e3
        inactive_workspace #002b36 #586e75 #002b36
        urgent_workspace #d33682 #d33682 #fdf6e3

        statusline         $white
        separator          $transparent
  }
}

This should change the i3 status bar.

You as well need i3blocks blocklets. "A blocklet is the configuration of a single block, part of the status line". You can find a comprehensive list of blocklets in the blocklets page.

In my setup, most of the scripts are taken from vivien blocklets.

Before you can proceed to get the blocklets scripts, edit the i3blocks.conf to define your icon fonts. Font-Awesome icons are used in this guide;

sudo vim /etc/i3blocks.conf

Replace the icons appropriately. e.g

Replace the html;

<i class="fa fa-tachometer"></i>

With the icon itself (Copy and Paste the ICON). And do the same for rest

# i3blocks config file
#
# Please see man i3blocks for a complete reference!
# The man page is also hosted at http://vivien.github.io/i3blocks
#
# List of valid properties:
#
# align
# color
# command
# full_text
# instance
# interval
# label
# min_width
# name
# separator
# separator_block_width
# short_text
# signal
# urgent

# Global properties
#
# The top properties below are applied to every block, but can be overridden.
# Each block command defaults to the script name to avoid boilerplate.
command=~/.config/i3/blocklets/$BLOCK_NAME
separator=false
separator_block_width= 10
markup=pango
align=right

# RAM usage
[memory]
interval=1
label=<i class="fa fa-tachometer"></i> 
color=#4CAF50

# CPU Usage
[cpu_usage]
label= <i class="fa fa-crosshairs" aria-hidden="true"></i>
interval=2
color=#87AFAF

# /home Partition Usage
[disk-home]
label=<i class="fa fa-home" aria-hidden="true"></i>:
interval=30
color=#586E75

# Network Interface IP
[iface]
color=#B4B7B4
interval=1
separator=false
label= <i class="fa fa-exchange" aria-hidden="true"></i>

# Wi-Fi SSID
[ssid]
label=  <i class="fa fa-wifi" aria-hidden="true"></i>
color=#d33682
interval=2

#Network Bandwidth
[bandwidth]
interval=1
color=#d33682

# Screen brightness
[brightness]
label= <i class="fa fa-adjust" aria-hidden="true"></i>
interval=1
signal=2
color=#738899

# Battery level
[battery]
interval=10

# Date and Time Calendar
[time]
label= <i class="fa fa-calendar"></i>
interval=1
color=#50C878

# Battery level notification
[batnotify]
interval=10
separator_block_width=4

Create a directory to store the blocklets scripts;

mkdir ~/.config/i3/blocklets

Some of the blocklets that are used in this setup are;

ls .config/i3/blocklets/ -1
bandwidth
batnotify
battery
brightness
cpu_usage
disk-home
iface
memory
ssid
time

Copy and paste the commands below to create the scripts contents;

RAM Usage;


cat > .config/i3/blocklets/memory << 'EOL'
#!/bin/sh
# Copyright (C) 2014 Julien Bonjean 

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see .

TYPE="${BLOCK_INSTANCE:-mem}"

awk -v type=$TYPE '
/^MemTotal:/ {
	mem_total=$2
}
/^MemFree:/ {
	mem_free=$2
}
/^Buffers:/ {
	mem_free+=$2
}
/^Cached:/ {
	mem_free+=$2
}
/^SwapTotal:/ {
	swap_total=$2
}
/^SwapFree:/ {
	swap_free=$2
}
END {
	if (type == "swap") {
		free=swap_free/1024/1024
		used=(swap_total-swap_free)/1024/1024
		total=swap_total/1024/1024
	} else {
		free=mem_free/1024/1024
		used=(mem_total-mem_free)/1024/1024
		total=mem_total/1024/1024
	}
	pct=used/total*100

	# full text
	printf("%.1fG/%.1fG (%.f%%)\n", used, total, pct)

	# short text
	printf("%.f%%\n", pct)

	# color
	if (pct > 90) {
		print("#FF0000\n")
	} else if (pct > 80) {
		print("#FFAE00\n")
	} else if (pct > 70) {
		print("#FFF600\n")
	}
}
' /proc/meminfo

case $BLOCK_BUTTON in
    1)
        termite -e  htop
        ;;
esac
EOL

CPU Usage script;


cat > .config/i3/blocklets/cpu_usage << 'EOL'
#!/usr/bin/perl
#
# Copyright 2014 Pierre Mavro 
# Copyright 2014 Vivien Didelot 
# Copyright 2014 Andreas Guldstrand 
#
# Licensed under the terms of the GNU GPL v3, or any later version.

use strict;
use warnings;
use utf8;
use Getopt::Long;

# default values
my $t_warn = 50;
my $t_crit = 80;
my $cpu_usage = -1;

sub help {
    print "Usage: cpu_usage [-w ] [-c ]\n";
    print "-w : warning threshold to become yellow\n";
    print "-c : critical threshold to become red\n";
    exit 0;
}

GetOptions("help|h" => \&help,
           "w=i"    => \$t_warn,
           "c=i"    => \$t_crit);

# Get CPU usage
$ENV{LC_ALL}="en_US"; # if mpstat is not run under en_US locale, things may break, so make sure it is
open (MPSTAT, 'mpstat 1 1 |') or die;
while () {
    if (/^.*\s+(\d+\.\d+)\s+$/) {
        $cpu_usage = 100 - $1; # 100% - %idle
        last;
    }
}
close(MPSTAT);

$cpu_usage eq -1 and die 'Can\'t find CPU information';

# Print short_text, full_text
printf "%.2f%%\n", $cpu_usage;
printf "%.2f%%\n", $cpu_usage;

# Print color, if needed
if ($cpu_usage >= $t_crit) {
    print "#C75D50\n";
    exit 33;
} elsif ($cpu_usage >= $t_warn) {
    print "#D7875F\n";
}

exit 0;
EOL

/home Partition Usage;


cat > .config/i3/blocklets/disk-home << 'EOL'
#!/bin/sh
# Copyright (C) 2014 Julien Bonjean 

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see .

DIR="${BLOCK_INSTANCE:-$HOME}"
ALERT_LOW="${1:-10}" # color will turn red under this value (default: 10%)

df -h -P -l "$DIR" | awk -v alert_low=$ALERT_LOW '
/\/.*/ {
	# full text
	print $4

	# short text
	print $4

	use=$5

	# no need to continue parsing
	exit 0
}

END {
	gsub(/%$/,"",use)
	if (100 - use < alert_low) {
		# color
		print "#FF0000"
	}
}
'
# Mouse settings
case $BLOCK_BUTTON in
    1) i3-msg exec 'caja --browser' ;;    # left click, locate +xdg-open files with rofi
    3) i3-msg exec ~/.config/i3/bin/rofi_finder # find files on right click
esac
EOL

Default route Network Interface IP


cat > .config/i3/blocklets/iface << 'EOL'
#!/bin/bash
# Copyright (C) 2014 Julien Bonjean 
# Copyright (C) 2014 Alexander Keller 

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see .

#------------------------------------------------------------------------

# Use the provided interface, otherwise the device used for the default route.
if [[ -n $BLOCK_INSTANCE ]]; then
  IF=$BLOCK_INSTANCE
else
  IF=$(ip route | awk '/^default/ { print $5 ; exit }')
fi

#------------------------------------------------------------------------

# As per #36 -- It is transparent: e.g. if the machine has no battery or wireless
# connection (think desktop), the corresponding block should not be displayed.
[[ ! -d /sys/class/net/${IF} ]] && exit

#------------------------------------------------------------------------

if [[ "$(cat /sys/class/net/$IF/operstate)" = 'down' ]]; then
  echo down # full text
  echo down # short text
  echo \#FF0000 # color
  exit
fi

case $1 in
  -4)
    AF=inet ;;
  -6)
    AF=inet6 ;;
  *)
    AF=inet6? ;;
esac

# if no interface is found, use the first device with a global scope
IPADDR=$(ip addr show $IF | perl -n -e "/$AF ([^\/]+).* scope global/ && print \$1 and exit")

case $BLOCK_BUTTON in
    1)
        termite -e 'ping 8.8.8.8'         ;;

    3) echo -n "$IPADDR" | xclip -q -se c 
        ;;
esac

#------------------------------------------------------------------------

echo "$IPADDR" # full text
echo "$IPADDR" # short text
EOL

Wi-Fi SSID (# Be sure to change the WLAN interface);

cat > .config/i3/blocklets/ssid << 'EOL'
#!/usr/bin/env bash
# Be sure to change the WLAN interface
echo "$(iw dev wlp0s20f3 link | grep SSID | cut -d " " -f 2-)"
EOL

Network Bandwidth;


cat > .config/i3/blocklets/bandwidth << 'EOL'
#!/bin/bash

# Use the provided interface, otherwise the device used for the default route.
if [[ -n $BLOCK_INSTANCE ]]; then
  INTERFACE=$BLOCK_INSTANCE
else
  INTERFACE=$(ip route | awk '/^default/ { print $5 ; exit }')
fi

# # if the connection is down, the corresponding block should not be displayed.
if ! [ -e "/sys/class/net/${INTERFACE}/operstate" ] || ! [ "`cat /sys/class/net/${INTERFACE}/operstate`" = "up" ]
then
    exit 0
fi

# path to store the old results in
path="/dev/shm/$(basename $0)-${INTERFACE}"

# grabbing data for each adapter.
read rx < "/sys/class/net/${INTERFACE}/statistics/rx_bytes"
read tx < "/sys/class/net/${INTERFACE}/statistics/tx_bytes"

# get time
time=$(date +%s)

# write current data if file does not exist. Do not exit, this will cause
# problems if this file is sourced instead of executed as another process.
if ! [[ -f "${path}" ]]; then
  echo "${time} ${rx} ${tx}" > "${path}"
  chmod 0666 "${path}"
fi

# read previous state and update data storage
read old < "${path}"
echo "${time} ${rx} ${tx}" > "${path}"

# parse old data and calc time passed
old=(${old//;/ })
time_diff=$(( $time - ${old[0]} ))

# sanity check: has a positive amount of time passed
[[ "${time_diff}" -gt 0 ]] || exit

# calc bytes transferred, and their rate in byte/s
rx_diff=$(( $rx - ${old[1]} ))
tx_diff=$(( $tx - ${old[2]} ))
rx_rate=$(( $rx_diff / $time_diff ))
tx_rate=$(( $tx_diff / $time_diff ))

# shift by 10 bytes to get KiB/s. If the value is larger than
# 1024^2 = 1048576, then display MiB/s instead

# outgoing
tx_kib=$(( $tx_rate >> 10 ))
if [[ "$tx_rate" -gt 1048576 ]]; then
    tx_mbs=$(printf '%s' "`echo "scale=1; $tx_kib / 1024" | bc`")
  echo -n "${tx_mbs}M."
else
  echo -n "${tx_kib}K."
fi

# incoming
rx_kib=$(( $rx_rate >> 10 ))
if [[ "$rx_rate" -gt 1048576 ]]; then
    rx_mbs=$( printf '%s' "`echo "scale=1; $rx_kib / 1024" | bc`")
  echo -n "${rx_mbs}M"
else
  echo -n "${rx_kib}K"
fi

# mouse buttons  
case $BLOCK_BUTTON in
    1) tm-cli ;; # transmission-remote-cli
    3) rofi-connm # rofi connection manager 
esac
EOL

System Battery status;

Check the battery instance and replace the value x in BATx;

ls /sys/class/power_supply/

cat > .config/i3/blocklets/battery << 'EOL'
!/bin/sh
# Copyright (C) 2014 Julien Bonjean 

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see .

INSTANCE="${1:-BAT1}"
ALERT_LOW="${2:-25}" # color will turn red under this value (default: 10%)
UPOWER="/usr/bin/upower"

if [ ! -x "$UPOWER" ]; then
	echo "upower not found"
	exit 1
fi

$UPOWER -i /org/freedesktop/UPower/devices/battery_$INSTANCE |
	awk -v alert_low=$ALERT_LOW '
/state:/ {
	state = $2
}
/time to full:/ {
	remaining_time = $4 " " substr ($5, 0, 1)
}
/time to empty:/ {
	remaining_time = $4 " " substr ($5, 0, 1)
}
/percentage:/ {
	percentage = $2;
}
END {
	if (state == "charging")
        label = ""
	else if (percentage == "100%")
		label = ""
	else if (percentage > 99)
		label = ""
	else if (percentage > 75)
		label = ""
	else if (percentage > 50)
		label = ""
	else if (percentage > 25)
		label = ""
    else if (percentage > 10) 
		label = ""
    else if (percentage > 5)  
		label = ""
	
    # full text & "$@" > /dev/null;
    print label " " percentage

	# short text
	print label " " percentage

	# color
	gsub(/%$/,"",percentage)
    if (percentage == "100")
		print "#c5c8c6"
    else if (state == "charging")
		print "#c5c8c6"
    else if (+ percentage < + alert_low)
        print "#cc6666"
    else if (percentage < 26)
        print "#af9f87"
    else
        print "#7ea3a3"
}
# mouse buttons
case $BLOCK_BUTTON in
  3) toggle-dpms ;; # left click, control DPMS 
  2) toggle-red ;;  # right click, redshift on/off
  1) getacpi ;; # dialog with battery info
  5) sudo brightness up ;; 
  # xbacklight doesn't work with modesetting use brightness script
  4) sudo brightness down ;; 
esac
EOL

Date and Time Calendar;

cat > .config/i3/blocklets/time << 'EOL'
#!/bin/bash
date_time=$(date '+%a %d-%m-%Y %R:%S')
echo "$date_time"

#Buttons Control
case "$BLOCK_BUTTON" in
    1) exec zenity --calendar
        ;;
esac
EOL

Battery Discharge Notification script.

Be sure to replace the battery instance, BATx accordingly.


cat > .config/i3/blocklets/batnotify << 'EOL'
#!/bin/bash

# Battery notifier script for i3
# First warning is at 30%,  Critical warning less than 15%

discharge_mode=`acpi -a | grep -o off`

# Get current battery level and set threshold
battery_level=$(cat /sys/class/power_supply/BAT1/capacity)
critical_value=15
warning_value=30

# Messages to print to notification
message="*** Battery level is ${battery_level}%, critical, sleeping in 30 seconds time ***"
warn_message="*** Battery level is ${battery_level}%, warning, connect your charger ***"

# Notification icon to use
not_icon="/usr/share/icons/gnome/scalable/status/battery-low-symbolic.svg"

if [ "$discharge_mode" == "off" ]; then
  if [  "$battery_level" -le "$critical_value" ]; then
    if [ -f "$not_icon" ]; then
        notify-send -u critical -i "$not_icon" -t 60000 "$message"
       # i3-nagbar -m "$message"
        sleep 300
        sudo  /lib/systemd/systemd-sleep hybrid-sleep
    else
         notify-send -u critical  -t 60000 "$message"
        #i3-nagbar -m "$message"
        sleep 120
        sudo  /lib/systemd/systemd-sleep hybrid-sleep

    fi
   elif [  "$battery_level" -eq "$warning_value" ]; then
     notify-send -u low -i "$not_icon" -t 60000 "$warn_message"
fi
fi
EOL

Ensure the blocklets are executable;

chmod +x ~/.config/i3/blocklets/*

This is how our i3 status bar now looks like;

i3 blocks

And that is pretty much it on our guide on how to install and setup i3 windows manager on Ubuntu 24.04. Feel free to customize this awesome tool to your liking. Enjoy!!

Further Reading

Refer to i3 user's guide for a comprehensive i3 reference.

i3 User's Guide

Other Tutorials

Install and Setup ZSH and Oh-My-Zsh on Ubuntu 20.04/Ubuntu 22.04

SUPPORT US VIA A VIRTUAL CUP OF COFFEE

We're passionate about sharing our knowledge and experiences with you through our blog. If you appreciate our efforts, consider buying us a virtual coffee. Your support keeps us motivated and enables us to continually improve, ensuring that we can provide you with the best content possible. Thank you for being a coffee-fueled champion of our work!

Photo of author
Kifarunix
Linux Certified Engineer, with a passion for open-source technology and a strong understanding of Linux systems. With experience in system administration, troubleshooting, and automation, I am skilled in maintaining and optimizing Linux infrastructure.

Leave a Comment