>inb4 i-if you want ur gay buttons go back to w10
current state of gnu/linux 2019

I'm not going into detail into why tiling window managers are awesome, that's already been done before. But I will attempt to help ease in the transition to i3 for those who are interested. For instance, I will share some details on reasonable configuration and some options and tricks that I have had success using. With this and future blog posts, I hope that the reader can gain some insight and build their own i3 configuration, which may look like setup, or completely different. It is true that this information already exists out there in some capacity, but having it condensed here may be helpful. With i3, this is how my desktop looks at the moment:

Example i3 desktop in practice

For those of you unaware, i3 is a GNU+Linux/BSD tiling window manager. The project's website cites that it is targeted toward advanced users and developers, although the software has exceptional documentation that is pretty easy to read. You will often see i3 shown off on image boards or the Unix Porn subreddit. While i3 can be configured to look quite aesthetic, the default configuration is incredibly ugly (well, simple). For most users, they tend to copy other people's configuration right away as opposed to building their own. This can be problematic in the same way as copying someone's .bashrc, you don't know exactly what each line in the configuration does, if you need it, or if it is going to do something you don't intend to happen. Thus, in writing blogs about this topic, I intend to inform users on ideas they can include rather than just dropping my whole dotfile on them.

I should also note that window managers are very different from complete desktop environments, and you shouldn't expect the exact same functionality. Window managers simply communicate with your X server to manage where windows are located on your screen and how your user input affects their behavior. Desktop environments (DE) contain all of the bells and whistles: widgets, status bars, lock screens, screen savers, default applications, etc. With i3wm, there are no buttons attached to every window which allows you to close or minimize windows, that is all handled with the keyboard for maximum efficiency. i3wm can come with some of the functionality of a DE, you can install i3bar and i3lock which are a default status bar and lock screen. I do use i3lock due to it's simplicity, but I have been instead using polybar for a status bar because I like some of its included functionality. In addition, there is no MS Windows-like "start menu" or dock where you can click to access the applications you typically use. Instead, default i3 uses dmenu, a much simpler program whose primary purpose is just meant to handle user input. In this case, dmenu is used to search for executables (I think just in /usr/bin) and execute them. Both polybar and dmenu are hefty topics I'll have to cover some time in the future, but first, we should talk about some standard options of the main i3 configuration file.

I'm going to assume you've managed to install i3 and set up xorg to automatically start i3 when you log in (or you've figured out how to actually get i3 to start when you need it to, at least). To configure it, you'll need to find and copy the default configuration file to an appropriate location, generally ~/.config/i3/config. Note any i3 settings can be changed temporarily by executing a terminal process i3-msg ____(some line you'd put in the file)____. Here you can start editing the existing structure to suit your needs, generally starting with the keybindings.

To understand how to handle keybindings, you should really read or learn about how to use i3 and how windows are moved around and sorted. You need to decide on a i3 modifier button (mod key). Holding this button will tell i3 that your key presses are meant to communicate with i3 as opposed to something else. Generally people pick either the super key (the one with the windows flag or something) or the alt key.

set $mod mod4
I'll have more on this topic in a subsequent blog. Next you should configure your navigation keys. By default, I think i3 uses the j through ; keys, but I have remapped them to vim keys. In addition, you can move floating windows with your mouse. And you can also set a key binding to kill focused windows.
# change focus
bindsym $mod+h focus left
bindsym $mod+j focus down
bindsym $mod+k focus up
bindsym $mod+l 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+h move left
bindsym $mod+Shift+j move down
bindsym $mod+Shift+k move up
bindsym $mod+Shift+l 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

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

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

Another related thing to set is how you tell i3 how you want to sort the windows. With the container layout, you can change how you want child windows to be spawned, as a new tile or stacked/tabbed on top of the parent Additionally, you can move a tiled window into a floating position in front of other windows or just make it full screen. And you can tell i3 to spawn new windows vertically or horizontally. For some of these motions, you may need to tell i3 to focus on the parent or child container to get the exact setup you want. Here are my settings:

# split in horizontal orientation
bindsym $mod+n split h
# split in vertical orientation
bindsym $mod+m split v
# enter fullscreen mode for the focused container
bindsym $mod+f fullscreen toggle

# change container layout (stacked, tabbed, toggle split)
bindsym $mod+y layout stacking
bindsym $mod+t layout tabbed
bindsym $mod+u 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

Now you can set up how you want to manage your workspaces. What should they be named, how you would you switch your view to another one, and should they be forced onto a specific monitor. Generally each workspace has a number, but I have heard of people putting special characters, like a firefox character, in the title and leaving a specific windows (like firefox) on that workspace. You can also force workspaces to stay on specific monitors. Speaking of which, people have complained about multiple-monitor setups, but I've never had ANY issue. I have also included a section on additional workspaces, because I have often found myself needing more than 10.

#Workspace Names
set $ws0 "0"
set $ws1 "1"
    ... #fill the rest in here, I am excluding for the point of space
set $ws29 "29"

# switch to workspace
bindsym $mod+0 workspace $ws0
    ...
bindsym $mod+9 workspace $ws9

# move focused container to workspace
bindsym $mod+Shift+0 move container to workspace $ws0
bindsym $mod+Shift+9 move container to workspace $ws9

#Display. Note these will differ from computer-to-computer
#You may need to change this to reflect what you see on arandr
set $monitor1 HDMI-1
set $monitor2 DP-1

#pin workspaces to specific monitors
workspace $ws1 output $monitor1
workspace $ws0 output $monitor2
workspace $ws9 output $monitor2
workspace $ws10 output $monitor2
workspace $ws19 output $monitor2
workspace $ws20 output $monitor2
workspace $ws29 output $monitor2

mode  "Alternate Workspaces 1" {
        bindsym $mod+0 workspace $ws10
            ...
        bindsym $mod+9 workspace $ws19

        bindsym $mod+Shift+0 move container to workspace $ws10
            ...
        bindsym $mod+Shift+9 move container to workspace $ws19

        bindsym Escape mode "default"
        bindsym Return mode "default"
}
mode  "Alternate Workspaces 2" {
        bindsym $mod+0 workspace $ws20
            ...
        bindsym $mod+9 workspace $ws29

        bindsym $mod+Shift+0 move container to workspace $ws20
            ...
        bindsym $mod+Shift+9 move container to workspace $ws29

        bindsym Escape mode "default"
        bindsym Return mode "default"
}
#Select workspace mode w/ mod+~ key etc
bindsym $mod+grave mode "Alternate Workspaces 1"
bindsym $mod+Shift+grave mode "Alternate Workspaces 2"

Now, let's talk about resizing windows. I have always used the default resize function, it has worked for me. If you're using i3-gaps, you can also change the gap spacing.

# 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 h resize shrink width 10 px or 10 ppt
        bindsym k resize grow height 10 px or 10 ppt
        bindsym j 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 or $mod+r
        bindsym Return mode "default"
        bindsym Escape mode "default"
        bindsym $mod+r mode "default"
}

bindsym $mod+r mode "resize"

##### i3-gaps Configuration #####
for_window [class="^.*"] border pixel 3
gaps inner 15
gaps outer 15
#Gaps adjustment
bindsym $mod+s gaps inner current plus 5
bindsym $mod+Shift+s gaps inner current minus 5
bindsym $mod+z gaps outer current plus 5
bindsym $mod+Shift+z gaps outer current minus 5
bindsym $mod+F11 gaps inner current set 0; gaps outer current set 0

There are probably a few programs you want to start immediately after logging in or restarting i3. And we can also set key bindings for starting other programs quickly.

#Compton for Transparency
exec_always compton

#arandr/xrandr multimonitor control, may need this to get a specific resolution or handle how multiple monitors are placed
exec ~/scripts/xrandr_2monitor.sh

#Polybar
exec_always ~/.config/polybar/polybarstart.sh

#Pulse Audio Applet
#exec --no-startup-id ~/.config/i3/i3_pa-applet

#Network Manager applet
#exec_always --no-startup-id nm-applet


#Program Launcher
#bindsym $mod+F1 exec dmenu_run
# There also is the (new) i3-dmenu-desktop which only displays applications shipping a .desktop file. 
#It is a wrapper around dmenu, so you need that installed.
#bindsym $mod+d exec --no-startup-id i3-dmenu-desktop
#bindsym $mod+F1 exec rofi -show run
bindsym $mod+F1 exec dmenu_run -i -l 15 -fn Monospace-18 -nb '#2c2c2e' -nf '#ff944d' -sb '#040404' -sf '#ff6600'

#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 'Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'"

#Applications
set $term urxvt
set $explorer thunar
set $browser qutebrowser --backend webengine

# start a terminal
bindsym $mod+Return exec $term

#lock screen
bindsym $mod+shift+x exec i3lock

#Screenshot keybindings
bindsym Print exec scrot
bindsym Shift+Print exec scrot -u

#video control
bindsym $mod+q exec arandr
#audio control
bindsym $mod+Shift+q exec pavucontrol

#printer control
bindsym $mod+p exec system-config-printer
#network control
bindsym $mod+Shift+p exec nm-connection-editor

#various program keybindings
bindsym $mod+e exec $term -e ranger
bindsym $mod+shift+e exec $explorer
bindsym $mod+w exec $browser
bindsym $mod+shift+w exec waterfox

And now for the fun part, let's set our aesthetic options. I use orange because it's usually pretty visible. You can experiment around with this to see what everything does. This should go without saying, but the #XXXXXX are standard hex colors.

#Default Colors
set $bg            #2c2c2e
set $fg            #9f9f9f
set $lo            #ff944d
set $hi            #ff6600
set $tx            #040404
set $ia            #8f8f8f

##### i3 Colors #####
#Window Colors
#                           border      background   text   indicator(i.e. where the next window will be tiled)
client.focused              $lo         $lo          $tx    $hi
client.unfocused            $bg         $bg          $ia
client.focused_inactive     $bg         $bg          $ia
client.urgent               $hi         $hi          $tx

##### 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
font pango:EnvyCodeR 12

##### Display ####
#I am using polybar, which is not configured here. But you could configure another bar with these.
###i3bar
# Start i3bar to display a workspace bar (plus the system information i3status finds out, if available)
#bar {
#        status_command i3status
#}

###i3blocks
#bar {
    #status_command i3blocks -c ~/.config/i3/i3blocks.conf
    #position top
    #mode dock
    #modifier None
    #colors {
    #    background $bg
    #    statusline $fg
    #    separator $lo
        #                   border          background          text
    #    focused_workspace   $lo             $bg                 $lo
    #    active_workspace    $tx             $bg                 $tx
    #    inactive_workspace  $ia             $bg                 $ia
    #    urgent_workspace    $hi             $bg                 $hi
    #}
#}

Last but not least, here are some miscellaneous things in my i3 config that I'll have to talk more about in the future, but here's a tease I guess.

#Runs Xmodmap to change keyboard settings for resetting mod key
exec if pacman -Q | grep -q "xmodmap"; then exec ~/scripts/no_terminal/keyboard.sh; fi;

#Wallpaper slideshow. Here we set the wallpaper, which will be dynamically updated with cron
exec xrdb ~/.Xresources
exec ~/scripts/themes/i3_theme_slideshow.sh
bindsym $mod+F5 exec ~/scripts/themes/themepick.sh

#Script Launcher
bindsym $mod+F2 exec ~/scripts/no_terminal/scriptstart_noterminal.sh
bindsym $mod+F3 exec ~/scripts/no_terminal/scriptstart_interminal.sh
#Unicode Character Selection
bindsym $mod+F6 exec ~/scripts/no_terminal/unicode_characters.sh

#audio keybindings
bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume 0 +5%
bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume 0 -5%
bindysm XF86AudioMute exec --nostartup-id pactl set-sink-mute 0 toggle

#Brightness Controls
bindsym XF86MonBrightnessUp exec xbacklight +10
bindsym XF86MonBrightnessDown exec xbacklight -10

#stop windows from closing from keybinding
bindsym ctrl+q exec ~/scripts/nothing.sh

#stops screen from immediately turning off
#can check with xset q
#see https://wiki.archlinux.org/index.php/Display_Power_Management_Signaling
exec xset s off -dpms