Francois Marier: Creating a modern tiling desktop environment using i3

Startup script
As soon as I log into my desktop, my startup script starts a few programs, including:
- gnome-settings-daemon: makes GTK applications look nice by applying my preferred theme amongst other things
- gnome-keyring-daemon: remembers ssh public keys for the duration of my session
- gnome-screensaver: locks the screen when I'm not around
- nm-applet: handles wifi and VPN connections
- git-annex: keeps my folders synchronized between machines
Because of a bug in gnome-settings-daemon which makes the mouse cursor disappear as soon as gnome-settings-daemon is started, I had to run the following to disable the offending gnome-settings-daemon plugin:
dconf write /org/gnome/settings-daemon/plugins/cursor/active false
Screensaver
In addition, gnome-screensaver didn't automatically lock my screen, so I installed xautolock and added it to my startup script:
xautolock -time 30 -locker "gnome-screensaver-command --lock" &
to lock the screen using gnome-screensaver after 30 minutes of inactivity.
I can also trigger it manually using the following shortcut defined in my ~/.i3/config
:
bindsym Ctrl+Mod1+l exec xautolock -locknow
Keyboard shortcuts
While keyboard shortcuts can be configured in GNOME, they don't work within i3, so I added a few more bindings to my ~/.i3/config
:
# volume control
bindsym XF86AudioLowerVolume exec /usr/bin/pactl set-sink-volume @DEFAULT_SINK@ -- '-5%'
bindsym XF86AudioRaiseVolume exec /usr/bin/pactl set-sink-volume @DEFAULT_SINK@ -- '+5%'
# brightness control
bindsym XF86MonBrightnessDown exec xbacklight -steps 1 -time 0 -dec 5
bindsym XF86MonBrightnessUp exec xbacklight -steps 1 -time 0 -inc 5
bindsym XF86AudioMute exec /usr/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle
# show battery stats
bindsym XF86Battery exec gnome-power-statistics
to make volume control, screen brightness and battery status buttons work as expected on my laptop.
These bindings require the following packages:
Keyboard layout switcher
Another thing that used to work with GNOME and had to re-create in i3 is the ability to quickly toggle between two keyboard layouts using the keyboard.
To make it work, I wrote a simple shell script and assigned a keyboard shortcut to it in ~/.i3/config
:
bindsym $mod+u exec /home/francois/bin/toggle-xkbmap
Suspend script
Since I run lots of things in the background, I have set my laptop to avoid suspending when the lid is closed by putting the following in /etc/systemd/login.conf
:
HandleLidSwitch=lock
Instead, when I want to suspend to ram, I use the following keyboard shortcut:
bindsym Ctrl+Mod1+s exec /home/francois/bin/s2ram
which executes a custom suspend script to clear the clipboards (using xsel), flush writes to disk and lock the screen before going to sleep.
To avoid having to type my sudo password every time pm-suspend is invoked, I added the following line to /etc/sudoers
:
francois ALL=(ALL) NOPASSWD: /usr/sbin/pm-suspend
Window and workspace placement hacks
While tiling window managers promise to manage windows for you so that you can focus on more important things, you will most likely want to customize window placement to fit your needs better.
Working around misbehaving applications
A few applications make too many assumptions about window placement and are just plain broken in tiling mode. Here's how to automatically switch them to floating mode:
for_window [class="VidyoDesktop"] floating enable
You can get the Xorg class of the offending application by running this command:
xprop grep WM_CLASS
before clicking on the window.
Keeping IM windows on the first workspace
I run Pidgin on my first workspace and I have the following rule to keep any new window that pops up (e.g. in response to a new incoming message) on the same workspace:
assign [class="Pidgin"] 1
Automatically moving workspaces when docking
Here's a neat configuration blurb which automatically moves my workspaces (and their contents) from the laptop screen (eDP1
) to the external monitor (DP2
) when I dock my laptop:
# bind workspaces to the right monitors
workspace 1 output DP2
workspace 2 output DP2
workspace 3 output DP2
workspace 4 output DP2
workspace 5 output DP2
workspace 6 output eDP1
You can get these output names by running:
xrandr --display :0 grep " connected"
Finally, because X sometimes fail to detect my external monitor when docking/undocking, I also wrote a script to set the displays properly and bound it to the appropriate key on my laptop:
bindsym XF86Display exec /home/francois/bin/external-monitor
dconf write /org/gnome/settings-daemon/plugins/cursor/active false
xautolock -time 30 -locker "gnome-screensaver-command --lock" &
to lock the screen using gnome-screensaver after 30 minutes of inactivity.
I can also trigger it manually using the following shortcut defined in my ~/.i3/config
:
bindsym Ctrl+Mod1+l exec xautolock -locknow
Keyboard shortcuts
While keyboard shortcuts can be configured in GNOME, they don't work within i3, so I added a few more bindings to my ~/.i3/config
:
# volume control
bindsym XF86AudioLowerVolume exec /usr/bin/pactl set-sink-volume @DEFAULT_SINK@ -- '-5%'
bindsym XF86AudioRaiseVolume exec /usr/bin/pactl set-sink-volume @DEFAULT_SINK@ -- '+5%'
# brightness control
bindsym XF86MonBrightnessDown exec xbacklight -steps 1 -time 0 -dec 5
bindsym XF86MonBrightnessUp exec xbacklight -steps 1 -time 0 -inc 5
bindsym XF86AudioMute exec /usr/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle
# show battery stats
bindsym XF86Battery exec gnome-power-statistics
to make volume control, screen brightness and battery status buttons work as expected on my laptop.
These bindings require the following packages:
Keyboard layout switcher
Another thing that used to work with GNOME and had to re-create in i3 is the ability to quickly toggle between two keyboard layouts using the keyboard.
To make it work, I wrote a simple shell script and assigned a keyboard shortcut to it in ~/.i3/config
:
bindsym $mod+u exec /home/francois/bin/toggle-xkbmap
Suspend script
Since I run lots of things in the background, I have set my laptop to avoid suspending when the lid is closed by putting the following in /etc/systemd/login.conf
:
HandleLidSwitch=lock
Instead, when I want to suspend to ram, I use the following keyboard shortcut:
bindsym Ctrl+Mod1+s exec /home/francois/bin/s2ram
which executes a custom suspend script to clear the clipboards (using xsel), flush writes to disk and lock the screen before going to sleep.
To avoid having to type my sudo password every time pm-suspend is invoked, I added the following line to /etc/sudoers
:
francois ALL=(ALL) NOPASSWD: /usr/sbin/pm-suspend
Window and workspace placement hacks
While tiling window managers promise to manage windows for you so that you can focus on more important things, you will most likely want to customize window placement to fit your needs better.
Working around misbehaving applications
A few applications make too many assumptions about window placement and are just plain broken in tiling mode. Here's how to automatically switch them to floating mode:
for_window [class="VidyoDesktop"] floating enable
You can get the Xorg class of the offending application by running this command:
xprop grep WM_CLASS
before clicking on the window.
Keeping IM windows on the first workspace
I run Pidgin on my first workspace and I have the following rule to keep any new window that pops up (e.g. in response to a new incoming message) on the same workspace:
assign [class="Pidgin"] 1
Automatically moving workspaces when docking
Here's a neat configuration blurb which automatically moves my workspaces (and their contents) from the laptop screen (eDP1
) to the external monitor (DP2
) when I dock my laptop:
# bind workspaces to the right monitors
workspace 1 output DP2
workspace 2 output DP2
workspace 3 output DP2
workspace 4 output DP2
workspace 5 output DP2
workspace 6 output eDP1
You can get these output names by running:
xrandr --display :0 grep " connected"
Finally, because X sometimes fail to detect my external monitor when docking/undocking, I also wrote a script to set the displays properly and bound it to the appropriate key on my laptop:
bindsym XF86Display exec /home/francois/bin/external-monitor
# volume control
bindsym XF86AudioLowerVolume exec /usr/bin/pactl set-sink-volume @DEFAULT_SINK@ -- '-5%'
bindsym XF86AudioRaiseVolume exec /usr/bin/pactl set-sink-volume @DEFAULT_SINK@ -- '+5%'
# brightness control
bindsym XF86MonBrightnessDown exec xbacklight -steps 1 -time 0 -dec 5
bindsym XF86MonBrightnessUp exec xbacklight -steps 1 -time 0 -inc 5
bindsym XF86AudioMute exec /usr/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle
# show battery stats
bindsym XF86Battery exec gnome-power-statistics
~/.i3/config
:
bindsym $mod+u exec /home/francois/bin/toggle-xkbmap
Suspend script
Since I run lots of things in the background, I have set my laptop to avoid suspending when the lid is closed by putting the following in /etc/systemd/login.conf
:
HandleLidSwitch=lock
Instead, when I want to suspend to ram, I use the following keyboard shortcut:
bindsym Ctrl+Mod1+s exec /home/francois/bin/s2ram
which executes a custom suspend script to clear the clipboards (using xsel), flush writes to disk and lock the screen before going to sleep.
To avoid having to type my sudo password every time pm-suspend is invoked, I added the following line to /etc/sudoers
:
francois ALL=(ALL) NOPASSWD: /usr/sbin/pm-suspend
Window and workspace placement hacks
While tiling window managers promise to manage windows for you so that you can focus on more important things, you will most likely want to customize window placement to fit your needs better.
Working around misbehaving applications
A few applications make too many assumptions about window placement and are just plain broken in tiling mode. Here's how to automatically switch them to floating mode:
for_window [class="VidyoDesktop"] floating enable
You can get the Xorg class of the offending application by running this command:
xprop grep WM_CLASS
before clicking on the window.
Keeping IM windows on the first workspace
I run Pidgin on my first workspace and I have the following rule to keep any new window that pops up (e.g. in response to a new incoming message) on the same workspace:
assign [class="Pidgin"] 1
Automatically moving workspaces when docking
Here's a neat configuration blurb which automatically moves my workspaces (and their contents) from the laptop screen (eDP1
) to the external monitor (DP2
) when I dock my laptop:
# bind workspaces to the right monitors
workspace 1 output DP2
workspace 2 output DP2
workspace 3 output DP2
workspace 4 output DP2
workspace 5 output DP2
workspace 6 output eDP1
You can get these output names by running:
xrandr --display :0 grep " connected"
Finally, because X sometimes fail to detect my external monitor when docking/undocking, I also wrote a script to set the displays properly and bound it to the appropriate key on my laptop:
bindsym XF86Display exec /home/francois/bin/external-monitor
HandleLidSwitch=lock
bindsym Ctrl+Mod1+s exec /home/francois/bin/s2ram
francois ALL=(ALL) NOPASSWD: /usr/sbin/pm-suspend
Working around misbehaving applications
A few applications make too many assumptions about window placement and are just plain broken in tiling mode. Here's how to automatically switch them to floating mode:
for_window [class="VidyoDesktop"] floating enable
You can get the Xorg class of the offending application by running this command:
xprop grep WM_CLASS
before clicking on the window.
Keeping IM windows on the first workspace
I run Pidgin on my first workspace and I have the following rule to keep any new window that pops up (e.g. in response to a new incoming message) on the same workspace:
assign [class="Pidgin"] 1
Automatically moving workspaces when docking
Here's a neat configuration blurb which automatically moves my workspaces (and their contents) from the laptop screen (eDP1
) to the external monitor (DP2
) when I dock my laptop:
# bind workspaces to the right monitors
workspace 1 output DP2
workspace 2 output DP2
workspace 3 output DP2
workspace 4 output DP2
workspace 5 output DP2
workspace 6 output eDP1
You can get these output names by running:
xrandr --display :0 grep " connected"
Finally, because X sometimes fail to detect my external monitor when docking/undocking, I also wrote a script to set the displays properly and bound it to the appropriate key on my laptop:
bindsym XF86Display exec /home/francois/bin/external-monitor
for_window [class="VidyoDesktop"] floating enable
xprop grep WM_CLASS
assign [class="Pidgin"] 1
Automatically moving workspaces when docking
Here's a neat configuration blurb which automatically moves my workspaces (and their contents) from the laptop screen (eDP1
) to the external monitor (DP2
) when I dock my laptop:
# bind workspaces to the right monitors
workspace 1 output DP2
workspace 2 output DP2
workspace 3 output DP2
workspace 4 output DP2
workspace 5 output DP2
workspace 6 output eDP1
You can get these output names by running:
xrandr --display :0 grep " connected"
Finally, because X sometimes fail to detect my external monitor when docking/undocking, I also wrote a script to set the displays properly and bound it to the appropriate key on my laptop:
bindsym XF86Display exec /home/francois/bin/external-monitor
# bind workspaces to the right monitors
workspace 1 output DP2
workspace 2 output DP2
workspace 3 output DP2
workspace 4 output DP2
workspace 5 output DP2
workspace 6 output eDP1
xrandr --display :0 grep " connected"
bindsym XF86Display exec /home/francois/bin/external-monitor