What do you think? Discuss, post comments, or ask questions at the end of this article [More about me]

I'm a big fan of i3 (tiling window manager for Linux).  I'm also a big fan of Arch and the user-friendly Manjaro Linux (which is based on Arch).  Put these together (i3 + Manjaro) and you get Manjaro i3 (Community Edition): a very nice distro with a well implemented i3wm environment (by default).

Tiling window managers do have a fairly steep learning curve, but dang, in terms of efficiency and managing many windows and tasks at once, you just can't beat a tiling window manager (for me anyway).

The below is a guide mostly just for me and covers some setup notes for my Manjaro i3 systems. 

The below guide was written largely for me and covers some setup notes for my Manjaro i3 systems. It might not work directly on your system as it depends (somewhat) on other applications I install/use (these are also outlined in the the guide below). In other words YMMV - and expect to have to modify the below to suit your needs.

Note: for brevity I'm going to refer to my Manjaro i3 system as Mi3 below.

Guide

Turn on firewall

Let's first enable the firewall (here we're using ufw):

sudo systemctl enable ufw
sudo ufw enable

We can set firewall config via the gufw:

sudo gufw

Enable TRIM for SSD

If you have an SSD, I'd suggest enabling the fstrim.timer service for TRIM.

See Enable periodic TRIM - including on a LUKS partition.

Trackpad setup

With i3 my hands hardly leave the keyboard and almost never reach for the mouse.  As such, I generally use my touchpad.  My preference is to disable mouse tapping, use 'natural scrolling' and disable 'horizontal scrolling'.  Although you can set all these settings using Manjaro i3's bmenu (mod+ctrl+b, and choose 'Hardware and drivers' → 'Configure touchpad'), these settings will not survive a reboot.

If you use libinput

To make these settings permanent, you can either add them to your .i3/config file, or set the options in /etc/X11/xorg.conf.d/30-touchpad.conf.  We're going to do the latter.  Edit the file using your preferred editor.  Below is an example of the settings I prefer.

/etc/X11/xorg.conf.d/30-touchpad.conf
Section "InputClass"
    Identifier "touchpad"
    Driver "libinput"
    MatchIsTouchpad "on"
    Option "Tapping" "off"
    Option "NaturalScrolling" "true"
    Option "HorizontalScrolling" "false"
EndSection

If you use (or prefer) xf86-input-synaptics

So, you can use the older arch synaptics driver instead of the newer libinput drivers.  Note that the synaptics driver is deprecated and hasn't been updated since 2012.  Having said that, on my Metabox P650RS-G the synaptics driver just feels better (the libinput drivers feel a bit "floaty", and not as responsive - I've yet to play around with it's config to improve the feel).

Let's first install the driver with pacman

sudo pacman -S xf86-input-synaptics

Once pacman installs, you'll need to copy /usr/share/X11/xorg.conf.d/70-synaptics.conf to the /etc/X11/xorg.conf.d

sudo cp /usr/share/X11/xorg.conf.d/70-synaptics.conf /etc/X11/xorg.conf.d

Now let's backup and then remove the current libinput touchpad conf file (which in my case was 30-touchpad.conf).

sudo mv 30-touchpad.conf 30-touchpad.conf.backup

I prefer natural scrolling with the touchpad, so let's modify 70-synaptics.conf to add this (note this is taken direclty from the official arch synaptics page):

Section "InputClass"
    Identifier "touchpad catchall"
    Driver "synaptics"
    MatchIsTouchpad "on"
	...
    Option "VertScrollDelta" "-111"
	Option "HorizScrollDelta" "-111"
...
EndSection

Note you'll need to reboot or restart X for the changes to take place.

Volume control

On all my laptops, I've been able to control volume with the standard volume up/down/mute keys (e.g. fn+f1 etc.) by installing volumeicon with

sudo pacman -S volumeicon

Once installed you'll need to add the following to your i3 config:

exec --no-startup-id volumeicon

Disable "beep" sound in terminal application

On one of my machines there was a very annoying "beep" sound that played whenever I did stuff (like hitting backspace too much in the terminal).  This got annoying pretty quickly.

I couldn't find a setting to disable this.  After some research it appears to be an X11 session property which can be disabled by running the following from terminal:

xset -b

You can make this stick after reboot by editing /etc/xprofile or ~/.xprofile (user specific setting) and adding the above command to either file.  If either file does not exist just create one.

Fixing Screen tearing (with Picom)

On Arch the Compton composite manager was recently renamed to Picom.  This article has been updated to reflect this. 

This requires the picom package to be installed (and active).  If you don't have this installed, do:

sudo pacman -S picom

To activate it from i3wm, add this line to your i3 config:

exec --no-startup-id picom -b

On one my laptops (Thinkpad e480) there was noticable screen tearing with picom enabled.  To eliminate the screen tearing found there were several tweaks needed to the ~/.config/picom.conf configuration file.  Below are the changes needed (note you'll need to replace the original settings below with these ones):

backend = "glx";
...
vsync = "opengl-swc";

Fixing QT5 applications (like VLC) UI scaling (if icons, fonts are too big)

On my Mi3 setup, I noticed that QT5 applications like VLC had huge icons and fonts were all messed up.  Now, I don't have a HiDPI screen (screen resolution is 1920x1080) but still had this issue.  Here's what ended up fixing this for me:

Add the following lines to your .profile:

export QT_QPA_PLATFORMTHEME="qt5ct"
export QT_AUTO_SCREEN_SCALE_FACTOR=0 
export QT_SCALE_FACTOR=1 

Restart then open up (install if not already installed) qt5ct (run from terminal).  Change settings and font to size 10 of some look that you like.  Here's settings that I quite like:

Hibernate (suspend to disk)

I sometimes prefer to hibernate my system, but unfortunately on one of my machines hibernation wasn't working.

See Use a swap file and enable hibernation on Arch Linux - including on a LUKS root partition.

Stop 2018 Razer Blade 15 waking right after sleep

One of my (nicer) machines (Razer Blade 15) wouldn't sleep, or at least stay asleep (kind of like my kids...).  It would immediately wake after trying to sleep.  Apparently, it's caused by the USB 3.0 chip used on the machine.

You can fix this by running (see Arch wiki here):

echo XHC | sudo tee /proc/acpi/wakeup

However, this needs to be run after every startup.  Let's use systemd to run this as a service.

First, create a service file by:

sudo nano /etc/systemd/system/xhc-sleep.service

and paste the following:

[Unit]
Description=Workaround for razer blade 15 waking after sleeping (USB 3.0 causing).

[Service]
ExecStart=echo XHC | tee /proc/acpi/wakeup

[Install]
WantedBy=multi-user.target

Now, let's enable and start the service:

sudo systemctl enable xhc-sleep.service
sudo systemctl start xhc-sleep.service

Note, even with this, after first starting up and then (the first) sleep - my machine wakes up immediately (unless I close my lid, which makes it stay asleep).  After that first "wake-up" it will now sleep properly (i.e. not wakeup automatically).

Stop 2019 Razer Blade 15 infinite suspend loop

On my 2019 Razer Blade 15, it would wake from suspend correctly on the first suspend after a boot.  Thereafter when it woke it would, after about 10 seconds, sleep again ad infinitum.

The ArchWiki gives the workaround for this issue in the form of a kernel parameter:

append the following kernel parameter to the GRUB_CMDLINE_LINUX_DEFAULT line in /etc/default/grub:

button.lid_init_state=open

After appending if should look something like line 4 in:

GRUB_DEFAULT=saved
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR='Manjaro'
GRUB_CMDLINE_LINUX_DEFAULT="quiet resume=UUID=f68ed3c5-da10-4288-890f-b83d8763e85e nvidia-drm.modeset=1 button.lid_init_state=open"
GRUB_CMDLINE_LINUX=""

# If you want to enable the save default function, uncomment the following
# line, and set GRUB_DEFAULT to saved.
GRUB_SAVEDEFAULT=true
...

Save the changes and then run:

sudo update-grub

Set default applications

We can generally set default (or preferred applications) in Mi3 by using the morec_menu (mod+z).  Navigate with mod+z → settings → preferred applications.  However, in my case, even setting my preferred browser to chrome (or chromium) didn't stick.

What did work though was modifying the ~/.config/mimeapps.list and replacing the default userapp-Pale Moon.desktop reference with google-chrome.desktop.

Alternatively, you can set the default http and https xdg-mime applications with:

xdg-mime default <browser>.desktop x-scheme-handler/http
xdg-mime default <browser>.desktop x-scheme-handler/https

where you can replace <browser> with you installed browser (e.g. pale-moon, firefox, chromium etc.).

Unlocking gnome-keyring on login

On many DEs that use gnome-keyring to securely store credentials (like usernames and passwords) they will automatically unlock the the keyring when logging in.  On i3... not so much.

To get i3 to successfully unlock your keyring on login, you'll need to use the method outlined here.

Edit /etc/pam.d/login and add the following two lines:

auth       optional     pam_gnome_keyring.so
session    optional     pam_gnome_keyring.so auto_start

After a restart (or logout/login) your gnome keyring should be unlocked.

Ricing (theming) and modifying i3

One of the beauties with i3 (and Linux in general) is that you can you modify your environment to suit how you like to work.  This is particularly true with i3 where you can modify not only how it looks but also how it behaves.

i3 makes this quite easy by providing a single config file where most changes can be made (~/.i3/config). 

Below is a copy of my config file that I usually implement to make the interface more appealing (to me).  Note the visual changes in my config are chosen to go along with the numix gtk theme (install with sudo pacman -S numix-gtk-theme).  It looks like this (screenshot running chrome, watching some netflix, and working in urxvt):


Note you don't have to be using manjaro-i3 to use this config.  If you're using stock Manjaro (or Arch) please ensure you have at least the following packages installed: i3-wm (or i3-gaps if you want dem' gaps), i3exit, i3status, py3status, and picom.  You can install all these packages with:

sudo pacman -S i3-wm i3exit i3status py3status picom

My config file:

Note that this config file contains other modifications that I prefer in my i3 setup, such as:

  • define mod_next at top of file: used throughout config, e.g.  mod=Mod1 (i.e. super), mod_next=Mod4 (i.e. alt)
  • conky config files (see following section)
  • also using rofi (sudo pacman -S rofi) for both window listing (mod+Tab) and as a launcher (mod+d);
  • using py3status instead of i3status (sudo pacman -S py3status);
  • change split h/v keys to mod+z|x (alternatively mod+mod_next+q|e)
  • using mod_next+u|i|o|p|[ keys for various apps (like launching pamac, chromium, bitwarden, putty, nautilus);
  • added resizing windows without needing resize mode and disabled resizing mode.  Can also use vim style keys here;
  • changes to container and splitting shortcuts; 
  • mod+mod_next+z, mod+mod+next+x increases/decreases current window transparency needs transset-df (sudo pacman -S transset-df);
  • sticky window toggle set to (mod+ctrl+s);
  • added "netflix" and "spotify" window settings (mod+mod_next+n, mod+mod_next+m);
  • added "redshift" mode (mod_next+r) to help my old ninja eyes...

I have several bindsyms that use integrated bash scripts (i.e. not external but explicitly defined in my i3 config) which depend on xdotool. Please ensure you have xdotool installed, e.g. do "pacman -S xdotool"

You'll note that I (perhaps peculiarly) use mod=Mod1 (super key) and mod_next=Mod4 (alt) instead of just using a single key mod key.  I thought I would briefly explain the reason why:

At work I'm in a rather peculiar environment where I usually have to work on a base windows environment (which I really only use for email) and then remote desktop into a variety of Linux desktops and dev environments (either running i3 or no gui at all).  As such, Super+L locks the host windows machine (which behaviour I am not permitted to change).

Hence, by necessity, I've moved to alt as the default mod key (since I'm a die-hard vim key fan), and now use the super key for mostly launching applications etc.  On my home machines I'm under no such restrictions (and just run straight Linux environments).  I did try to get used to two different configs (one at work and one at home) but my muscle memory didn't like that so I settled on the current config which I'm now used to.

Contents of my ~/.i3/config
# i3 config file (v4)
# Please see http://i3wm.org/docs/userguide.html for a complete reference!

# MISC. SETTERS
# Set mod key ($mod_next=<Alt>, Mod4=<Super>)
set $mod Mod1
set $mod_next Mod4
set $border_no_name border pixel 3
set $border_normal border normal 3

# set i3-input font
set $i3inputfont \\"-*-*-*-*-*-*-24-*-*-*-*-*-*-*\\"  

# Theme options (comment/uncomment theme group)
# Theme 1 "fluorescent blue"
set $accent-bg #07eded
set $indicator #f81212

# Theme 2 "french pink"
#set $accent-bg #f57a9d
#set $indicator #109648

# Theme 3 "paradise pink"
#set $accent-bg #eb5ca3
#set $indicator #109648

# Theme 4 "sheen green"
#set $accent-bg #8ae234
#set $indicator #109648

# Theme 5 "illuminating emerald"
#set $accent-bg #00916e
#set $accent-txt #F9FAF9
#set $indicator #109648

# Theme 6 "light gray"
#set $accent-bg #D3D3D3
#set $accent-txt #363636
#set $indicator #109648

# Theme 7 "yellow green"
#set $accent-bg #8ac926
#set $accent-txt #363636
#set $indicator #109648

# set other colors
set $accent-txt #000000
set $inactive-bg #00000099
set $inactive-txt #bdbbbb
set $unfocused-bg #00000099
set $unfocused-txt #939f9f

# class                  border       backgr.    text        indic.     child_border
client.focused           $accent-bg $accent-bg $accent-txt $indicator $accent-bg
client.focused_inactive  $inactive-bg $inactive-bg $accent-bg $indicator $inactive-bg
client.unfocused         $unfocused-bg $unfocused-bg $unfocused-txt $indicator $unfocused-bg
client.urgent           #CB4B16 #FDF6E3 #CB4B16 $indicator
#client.placeholder      #000000 #0c0c0c $accent-txt #000000
#client.background       #2B2C2B

# set default desktop layout (default is tiling) <default|stacking|tabbed>
workspace_layout tabbed

# set my quick tabbed/stacked toggle
bindsym $mod+e layout toggle tabbed stacked

# set default window title_align
title_align center

# Configure border style <normal|1pixel|pixel xx|none|pixel>
for_window [class=".*"] $border_normal
for_window [class=".*"] title_window_icon on
for_window [class=".*"] title_window_icon padding 3px

## i3-overview (https://github.com/milgra/i3-overview)
#for_window [class="i3-overview"] floating enable
#for_window [class="i3-overview"] sticky enable
#no_focus [class="i3-overview"]
#exec --no-startup-id i3-overview

# focus_wrapping <yes|no|force|workspace>
# Legacy syntax: "force_focus_wrapping force"
focus_wrapping no
# parent focus switch (useful for master/stack switching) - has fallback for no focus_wrapping
# required xdotool
#set $focusroot x=$(xdotool getwindowfocus getwindowname); while [ \\"$x\\" != \\"i3\\" ]; do i3-msg \\"focus parent\\"; x=$(xdotool getwindowfocus getwindowname); done
set $focusroot for _ in {1..4}; do i3-msg \\"focus parent\\"; done
set $unfocusroot for _ in {1..3}; do i3-msg \\"focus child\\"; done
bindsym $mod+r exec --no-startup-id "WINDOW=$(xdotool getwindowfocus); $focusroot; i3-msg \\"focus child, focus left\\"; $unfocusroot; x=$(xdotool getwindowfocus); if [ \\"$x\\" == \\"$WINDOW\\" ]; then $focusroot; i3-msg \\"focus child, focus right\\"; fi"

# Hide borders <none|vertical|horizontal|both|smart>
hide_edge_borders none

# set popup behaviour during full screen <smart|ignore|leave_fullscreen>
popup_during_fullscreen leave_fullscreen

# change borders
bindsym $mod+$mod_next+b $border_normal
bindsym $mod+Shift+b $border_no_name
bindsym $mod+Ctrl+b border none

# xrandr set to default res (needed if unplug monitor and can't see screen)
bindsym $mod+backslash exec --no-startup-id "xrandr --output eDP-1-1 --mode 2560x1440 --rate 240; xrandr --output eDP-1 --mode 2560x1440 --rate 240"
bindsym $mod+BackSpace exec --no-startup-id "source ~/.xprofile; xmodmap ~/.Xmodmap"

# 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
font pango:DejaVu Sans 11

# Use Mouse+$mod to drag floating windows
floating_modifier $mod

# Autostart applications
#exec --no-startup-id alttab -pk h -nk l -fg "#d58681" -bg "#4a4a4a" -frame "#eb564d" -t 128x150 -i 127x64
# needs hsetroot installed
#exec_always --no-startup-id hsetroot -solid "#000000"
exec_always --no-startup-id /usr/bin/nitrogen --restore
exec --no-startup-id "pkill -9 redshift; redshift -P -t 5000:4000"
exec --no-startup-id "xkbset exp =m; xkbset m"
exec --no-startup-id /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1
exec --no-startup-id /usr/lib/xfce4/notifyd/xfce4-notifyd
exec --no-startup-id copyq
exec --no-startup-id fcitx -d
exec --no-startup-id nm-applet
exec --no-startup-id optimus-manager-qt
exec --no-startup-id xfce4-power-manager
exec_always --no-startup-id pkill conky && sleep 0.5; conky -c ~/.config/conky; conky -c ~/.config/conky_shortcuts
set $picom_start "pkill picom; sleep 1; picom -b"
exec_always --no-startup-id $picom_start
#exec --no-startup-id yes | xsm --restore

# picom (compositor)
bindsym $mod+t exec --no-startup-id $picom_start
bindsym $mod+ctrl+t exec --no-startup-id "killall picom"

# tint2 configuration (needs tint2 package)
exec_always --no-startup-id killall tint2 && sleep 0.5; tint2
for_window [class="(?i)^tint2conf$"] floating disable
# subscribe to urgent event and set _NET_WM_STATE_DEMANDS_ATTENTION (for tint2)
exec_always --no-startup-id i3-msg -t subscribe -m '[ "window" ]' | jq --unbuffered -Mrc '. | select(.change == "urgent" and .container.urgent == true and .container.focused == false) | .container.window' | xargs -I{} xprop -id {} -f _NET_WM_STATE 32a -set _NET_WM_STATE _NET_WM_STATE_DEMANDS_ATTENTION
# subscribe to urgent event being selected  and set _NET_WM_STATE_FOCUSED (for tint2)
exec_always --no-startup-id i3-msg -t subscribe -m '[ "window" ]' | jq --unbuffered -Mrc '. | select(.change == "urgent" and .container.focused == true) | .container.window' | xargs -I{} xprop -id {} -f _NET_WM_STATE 32a -set _NET_WM_STATE _NET_WM_STATE_FOCUSED

# never steal focus
focus_on_window_activation urgent
bindsym $mod+period [urgent=latest] focus

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

# start program launcher
#bindsym $mod+d exec --no-startup-id dmenu_recency
bindsym $mod_next+Tab exec --no-startup-id "rofi -show-icons -modi window,drun -show window -scroll-method 1 -kb-element-next \\"\\" -kb-element-next \\"\\" -kb-mode-next \\"Tab\\" -kb-row-up \\"Super+k\\" -kb-row-down \\"Super+j\\" -theme lb -theme-str '* { font: \\"DejaVu Sans Mono 16\\"; foreground: #ffffff; border-color: $accent-bg; separatorcolor: $accent-bg; selected-normal-background: $accent-bg; } window { height: 80%; }'"

# instant layout
# REQUIRES i3-instant-layout and XDOTOOL
#set $centre_mouse WINDOW=$(xdotool getactivewindow); eval `xdotool getwindowgeometry --shell $WINDOW`; W=`expr $WIDTH / 2`; H=`expr $HEIGHT / 2`; xdotool mousemove --window $WINDOW $W $H
#bindsym $mod+Escape exec --no-startup-id "$centre_mouse; i3-instant-layout --list | rofi -show-icons -sort -kb-row-up \\"Alt+k\\" -kb-row-down \\"Alt+j\\" -theme lb -theme-str '* { font: \\"Sans 16\\"; foreground: #ffffff; border-color: $accent-bg; separatorcolor: $accent-bg; selected-normal-background: $accent-bg; }' -dmenu -i | i3-instant-layout -

################################################################################################
## sound-section - DO NOT EDIT if you wish to automatically upgrade Alsa -> Pulseaudio later! ##
################################################################################################

exec --no-startup-id volumeicon
bindsym $mod+$mod_next+v exec --no-startup-id "killall volumeicon; sleep 1; volumeicon"
#bindsym $mod+Ctrl+m exec --no-startup-id terminal -e 'alsamixer'
#exec --no-startup-id pulseaudio
#exec --no-startup-id pa-applet
#bindsym $mod+Ctrl+m exec --no-startup-id pavucontrol

################################################################################################

# Increase/decrease sink volume 1
bindsym $mod+F1 exec --no-startup-id amixer -qD pulse set Master toggle; exec notify-send 'sound toggled'
bindsym $mod+F2 exec --no-startup-id amixer -qc 0 set Master 2db-; exec notify-send 'volume decreased'
bindsym $mod+F3 exec --no-startup-id amixer -qc 0 set Master 2db+; exec notify-send 'volume increased'

# Screen brightness controls
bindsym $mod_next+F8 exec --no-startup-id "sleep 1; xset dpms force off"
# requires acpilight 
bindsym $mod+F8 exec --no-startup-id sudo xbacklight -ctrl intel_backlight -dec 5 -fps 60
bindsym $mod+F9 exec --no-startup-id sudo xbacklight -ctrl intel_backlight -inc 5 -fps 60

# focus_follows_mouse no

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

# wasd focus
bindsym $mod+w focus up
bindsym $mod+a focus left
bindsym $mod+s focus down
bindsym $mod+d focus right

# container focusing (with fallback for case where window is direct child of workspace container)
# NOTE: requires xdotool
#bindsym $mod+comma exec --no-startup-id "WINDOW=$(xdotool getactivewindow); i3-msg \\"focus parent; focus left; focus child\\"; NEW_WINDOW=$(xdotool getactivewindow); if [ \\"$NEW_WINDOW\\" -eq \\"$WINDOW\\" ]; then i3-msg \\"focus left\\"; fi"
#bindsym $mod+period exec --no-startup-id "WINDOW=$(xdotool getactivewindow); i3-msg \\"focus parent; focus right; focus child\\"; NEW_WINDOW=$(xdotool getactivewindow); if [ \\"$NEW_WINDOW\\" -eq \\"$WINDOW\\" ]; then i3-msg \\"focus right\\"; fi"

# convenience move
bindsym $mod+z move left
bindsym $mod+x move right
bindsym $mod+Shift+z move left; focus right
bindsym $mod+Shift+x move right; focus left

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

bindsym $mod+Ctrl+Shift+h move left 1px
bindsym $mod+Ctrl+Shift+j move down 1px
bindsym $mod+Ctrl+Shift+k move up 1px
bindsym $mod+Ctrl+Shift+l move right 1px

# wasd move
bindsym $mod+Shift+w move up 50px
bindsym $mod+Shift+a move left 50px
bindsym $mod+Shift+s move down 50px
bindsym $mod+Shift+d move right 50px

# move the currently focused window to the scratchpad
bindsym $mod+Shift+minus move scratchpad

# Show the next scratchpad window or hide the focused scratchpad window.
# If there are multiple scratchpad windows, this command cycles through them.
bindsym $mod+minus scratchpad show

# move window to mark (by workspace)
# requires jq
#set $setwn wn=$(i3-msg -t get_workspaces | jq '.[] | select(.focused==true).num');
#bindsym $mod+Tab exec --no-startup-id "$setwn i3-msg \\"[con_mark=\\"$wn\\"] focus, focus child\\""
#bindsym $mod+Shift+Tab exec --no-startup-id "$setwn mwn=$(echo \\"m$wn\\"); i3-msg \\"mark $mwn, [con_mark=\\"$mwn\\"] move window to mark $wn, unmark $mwn\\"
#bindsym $mod+Escape exec --no-startup-id "$setwn i3-msg \\"[workspace=__focused__] move window to mark $wn\\"
#bindsym $mod+$mod_next+Tab exec --no-startup-id "$setwn i3-msg \\"split h, layout stacking, focus parent, mark --add --toggle $wn, focus child\\"

## mark and focus
#bindsym $mod+Ctrl+1 mark --add --toggle 1
#bindsym $mod+Ctrl+2 mark --add --toggle 2
#bindsym $mod+Ctrl+3 mark --add --toggle 3
#bindsym $mod+Ctrl+4 mark --add --toggle 4
#bindsym $mod+Ctrl+5 mark --add --toggle 5
#bindsym $mod+Ctrl+6 mark --add --toggle 6
#bindsym $mod+Ctrl+7 mark --add --toggle 7
#bindsym $mod+Ctrl+8 mark --add --toggle 8
#bindsym $mod+Ctrl+9 mark --add --toggle 9

# workspace back and forth (with/without active container)
workspace_auto_back_and_forth yes

# renaming container
set $namechildcon "i3-msg focus parent; i3-input -f \\"-*-*-*-*-*-*-24-*-*-*-*-*-*-*\\" -P \\"Name child container: \\" -F 'title_format \\"<span><b>%s</b>%title</span>\\"'; i3-msg focus child"
bindsym $mod+slash exec --no-startup-id $namechildcon
# sets back to default i3 container title
bindsym $mod+$mod_next+slash focus parent; title_format " %title"; focus child

# container layouts
bindsym $mod_next+w layout tabbed
bindsym $mod_next+q layout splith
bindsym $mod_next+e layout splitv
bindsym $mod_next+s layout stacking

# child container layout bindsyms (creates a child container from currently select window)
bindsym $mod+c split h, layout splitv, focus parent, $border_no_name, focus child
bindsym $mod+$mod_next+c split h, layout tabbed
bindsym $mod+$mod_next+z focus left; move right
bindsym $mod+$mod_next+x focus right; move left

# toggle fullscreen mode for the focused container
bindsym $mod+f fullscreen toggle
bindsym $mod+shift+f exec --no-startup-id "i3-msg focus parent, fullscreen toggle, focus child"

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

# change focus between tiling / floating windows
bindsym $mod+Ctrl+space focus mode_toggle

# toggle sticky
bindsym $mod+Ctrl+s sticky toggle;exec --no-startup-id notify-send 'sticky windows toggled'

# window transparency adjustment (and alias to restart picom)
bindsym $mod+$mod_next+F8 exec --no-startup-id transset-df -a --min 0.20 --dec 0.20
bindsym $mod+$mod_next+Shift+F8 exec --no-startup-id transset-df -a --min 0.1 --dec 0.1
bindsym $mod+$mod_next+Ctrl+F8 exec --no-startup-id "WINDOWS=$(xdotool search --all --onlyvisible --desktop $(xprop -notype -root _NET_CURRENT_DESKTOP | cut -c 24-) \\"\\" 2>/dev/null); for window in $WINDOWS; do xdotool windowactivate $window; transset-df -a --min 0.20 --dec 0.20; done"
bindsym $mod+$mod_next+F9 exec --no-startup-id transset-df -a --inc 0.20 --max 0.99
bindsym $mod+$mod_next+Shift+F9 exec --no-startup-id transset-df -a --inc 0.1 --max 0.99
bindsym $mod+$mod_next+Ctrl+F9 exec --no-startup-id "WINDOWS=$(xdotool search --all --onlyvisible --desktop $(xprop -notype -root _NET_CURRENT_DESKTOP | cut -c 24-) \\"\\" 2>/dev/null); for window in $WINDOWS; do xdotool windowactivate $window; transset-df -a --inc 0.20 --max 0.99; done"

# window dimming enable or disable (uses xdotool and xprop to set a anti-dim flag, which picom recognises in focus-exclude array)
bindsym $mod+ctrl+a exec --no-startup-id xprop -id $(xdotool getactivewindow) -f ANTIDIM_FLAG 8c -set ANTIDIM_FLAG 1; exec --no-startup-id notify-send 'anti-dim set on window'
bindsym $mod+ctrl+Shift+a exec --no-startup-id xprop -id $(xdotool getactivewindow) -remove ANTIDIM_FLAG; exec --no-startup-id notify-send 'dim set on window'

# window colour inversion (uses xrandr-invert-colors, xdotool, and xprop to set an invert flag, which picom recognises in invert-color-include array)
bindsym $mod+ctrl+i exec --no-startup-id xrandr-invert-colors
bindsym $mod+$mod_next+i exec --no-startup-id xprop -id $(xdotool getactivewindow) -f INVERT_FLAG 8c -set INVERT_FLAG 1; 
bindsym $mod++Shift+i exec --no-startup-id xprop -id $(xdotool getactivewindow) -remove INVERT_FLAG;

# focus the parent container
bindsym $mod+Escape focus parent
bindsym $mod+$mod_next+Escape focus child

# Workspace names
# to display names or symbols instead of plain workspace numbers you can use
# something like: set $ws1 1:mail
#                 set $ws2 2:
set $ws1 number 1
set $ws2 number 2
set $ws3 number 3
set $ws4 number 4
set $ws5 number 5
set $ws6 number 6
set $ws7 number 7
set $ws8 number 8
set $ws9 number 9

# numbered workspace bindsyms 
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+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+$mod_next+1 move container to workspace $ws1, workspace $ws1
bindsym $mod+$mod_next+2 move container to workspace $ws2, workspace $ws2
bindsym $mod+$mod_next+3 move container to workspace $ws3, workspace $ws3
bindsym $mod+$mod_next+4 move container to workspace $ws4, workspace $ws4
bindsym $mod+$mod_next+5 move container to workspace $ws5, workspace $ws5
bindsym $mod+$mod_next+6 move container to workspace $ws6, workspace $ws6
bindsym $mod+$mod_next+7 move container to workspace $ws7, workspace $ws7
bindsym $mod+$mod_next+8 move container to workspace $ws8, workspace $ws8
bindsym $mod+$mod_next+9 move container to workspace $ws9, workspace $ws9

# switching back and forth
bindsym $mod+Tab workspace back_and_forth
bindsym $mod+Shift+Tab move container to workspace back_and_forth
bindsym $mod+$mod_next+Tab move container to workspace back_and_forth; workspace back_and_forth

# dynamic workspace operations
bindsym $mod_next+a workspace prev
bindsym $mod_next+d workspace next
bindsym $mod_next+1 exec --no-startup-id i3-input -f $i3inputfont -P "Go to Workspace (number): " -l 2 -F 'workspace number "%s"'
bindsym $mod_next+2 exec --no-startup-id i3-input -f $i3inputfont -P "Go to Workspace (name): " -F 'workspace "%s"'
bindsym $mod_next+Shift+1 exec --no-startup-id i3-input -f $i3inputfont -P "Move to Workspace (number): " -l 2  -F 'move container to workspace number "%s"'
bindsym $mod_next+Shift+2 exec --no-startup-id i3-input -f $i3inputfont -P "Move to Workspace (name): " -F 'move container to workspace "%s"'
bindsym $mod_next+grave exec --no-startup-id i3-input -f $i3inputfont -P "Rename Workspace: " -F 'rename workspace to "%s"'

# iterative workspace operations
set $workspace_dynamic $(($(i3-msg -t get_workspaces | tr , '\n' | grep '\\"num\\":' | cut -d : -f 2 | sort -rn | head -1) + 1))
bindsym $mod+grave exec --no-startup-id "i3-msg workspace $workspace_dynamic"
bindsym $mod+Shift+grave exec --no-startup-id "i3-msg move container to workspace $workspace_dynamic"
bindsym $mod+$mod_next+grave exec --no-startup-id "i3-msg move container to workspace $workspace_dynamic, workspace number $workspace_dynamic"

# Open applications on specific workspaces
# assign [class="Thunderbird"] $ws1
# assign [class="Pale moon"] $ws2
# assign [class="Pcmanfm"] $ws3
# assign [class="Skype"] $ws5

# Open specific applications in floating mode
for_window [class="(?i)Gcolor3"] floating enable border pixel 1
for_window [class="(?i)Gnome-calculator"] floating enable
for_window [class="(?i)Kupfer"] border none
for_window [class="(?i)System-config-printer.py"] floating enable border normal
for_window [class="(?i)arandr"] floating enable
for_window [class="Calamares"] floating enable border normal
for_window [class="Clipgrab"] floating enable
for_window [class="Galculator"] floating enable border pixel 1
for_window [class="Lightdm-gtk-greeter-settings"] floating enable
for_window [class="Manjaro-hello"] floating enable
for_window [class="Qtconfig-qt4"] floating enable sticky enable border normal
for_window [class="Shutter"] floating disable
for_window [class="Simple-scan"] floating enable border normal
for_window [class="Thus"] floating enable border normal
for_window [class="Timeset-gui"] floating enable border normal
for_window [class="Xfburn"] floating enable
for_window [class="copyq"] floating enable border pixel 1
for_window [class="octopi"] floating enable
for_window [class="qt5ct"] floating enable sticky enable border normal
for_window [class="spectacle"] floating disable
for_window [title="File Transfer*"] floating enable
for_window [title="alsamixer"] floating enable border pixel 1
for_window [class="(?i)^timeshift-gtk$"] floating disable
for_window [class="(?i)^gnome-calculator$"] floating disable
for_window [class="(?i)^workspacesclient$"] floating disable
for_window [class="(?i)^zoom$"] floating disable
for_window [class="(?i)nvidia-settings"] floating enable

# Application shortcuts
bindsym $mod_next+u exec --no-startup-id pamac-manager
bindsym $mod_next+i exec --no-startup-id brave
bindsym $mod_next+o exec --no-startup-id xfce4-appfinder
bindsym $mod_next+p exec --no-startup-id putty
bindsym $mod_next+bracketleft exec --no-startup-id nautilus
# type clipboard contents (required xdotool and xclip)
bindsym $mod+Shift+Ctrl+v exec --no-startup-id "sleep 1; /usr/bin/xdotool type --delay 100 \\"$(xclip -o)\\""

# shortcuts to often used applications
bindsym $mod+Return exec --no-startup-id i3-sensible-terminal
bindsym Print exec --no-startup-id flameshot gui
bindsym $mod_next+Ctrl+x --release exec --no-startup-id xkill

#sm-player shortcuts (e.g. for use if send smplayer to scratchpad)
bindsym $mod_next+Shift+space exec --no-startup-id smplayer -send-action pause
bindsym $mod_next+Shift+a exec --no-startup-id smplayer -send-action rewind1
bindsym $mod_next+Shift+d exec --no-startup-id smplayer -send-action forward1
bindsym $mod_next+Shift+h exec --no-startup-id smplayer -send-action rewind1
bindsym $mod_next+Shift+l exec --no-startup-id smplayer -send-action forward1

# reload the configuration file
bindsym $mod+Ctrl+Shift+c reload

# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)
bindsym $mod+Ctrl+r restart

bindsym $mod_next+l exec --no-startup-id i3exit lock

# exit i3 (logs you out of your X session)
#bindsym $mod+Shift+e exec --no-startup-id "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'"

# Set shut down, restart and locking features
bindsym $mod+0 mode "$mode_system"
set $mode_system (l)ock, (e)xit, switch_(u)ser, (Shift+s)uspend, (s)uspend+lock, (h)ibernate, (Shift+h)ibernate+lock, (r)eboot, shut(d)own
mode "$mode_system" {
    bindsym l exec --no-startup-id i3exit lock, mode "default"
    bindsym Shift+s exec --no-startup-id "systemctl suspend", mode "default"
    bindsym s exec --no-startup-id "i3exit lock; systemctl suspend", mode "default"
    bindsym u exec --no-startup-id "i3exit switch_user", mode "default"
    # requires xsm (xsession-manager)
    bindsym e exec --no-startup-id "yes | xsm --save; i3exit logout", mode "default"
    bindsym h exec --no-startup-id "systemctl hibernate", mode "default"
    bindsym Shift+h exec --no-startup-id "i3exit lock; systemctl hibernate", mode "default"
    bindsym r exec --no-startup-id "yes | xsm --save; i3exit reboot", mode "default"
    bindsym d exec --no-startup-id "yes | xsm --save; i3exit shutdown", mode "default"

    # exit system mode: "Enter" or "Escape"
    bindsym Return mode "default"
    bindsym Escape mode "default"
}

## Resize window (you can also use the mouse for that)
#bindsym $mod+r mode "resize"
#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 l resize shrink width 5 px or 5 ppt
        #bindsym j resize grow height 5 px or 5 ppt
        #bindsym k resize shrink height 5 px or 5 ppt
        #bindsym semicolon resize grow width 5 px or 5 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

        ## exit resize mode: Enter or Escape
        #bindsym Return mode "default"
        #bindsym Escape mode "default"
#}

# wasd key resizing without resize mode
bindsym $mod+$mod_next+a resize shrink width 50 px or 5 ppt
bindsym $mod+$mod_next+s resize grow height 50 px or 5 ppt
bindsym $mod+$mod_next+w resize shrink height 50 px or 5 ppt
bindsym $mod+$mod_next+d resize grow width 50 px or 5 ppt
bindsym $mod+$mod_next+Shift+a resize shrink width 100 px or 10 ppt
bindsym $mod+$mod_next+Shift+s resize grow height 100 px or 10 ppt
bindsym $mod+$mod_next+Shift+w resize shrink height 100 px or 10 ppt
bindsym $mod+$mod_next+Shift+d resize grow width 100 px or 10 ppt

# hkjl resize
bindsym $mod+$mod_next+h resize shrink width 50 px or 5 ppt
bindsym $mod+$mod_next+j resize grow height 50 px or 5 ppt
bindsym $mod+$mod_next+k resize shrink height 50 px or 5 ppt
bindsym $mod+$mod_next+l resize grow width 50 px or 5 ppt
bindsym $mod+$mod_next+Shift+h resize shrink width 100 px or 10 ppt
bindsym $mod+$mod_next+Shift+j resize grow height 100 px or 10 ppt
bindsym $mod+$mod_next+Shift+k resize shrink height 100 px or 10 ppt
bindsym $mod+$mod_next+Shift+l resize grow width 100 px or 10 ppt

# "netflix" and "spotify" modes
bindsym $mod+$mod_next+n floating enable;sticky enable; move position 1632px 864px resize set 912 543; border none
bindsym $mod+$mod_next+m floating enable;sticky enable; move position 1123px 983px resize set 791 70; border none
bindsym $mod+$mod_next+Shift+m resize set height 64; border none

# redshift modes
bindsym $mod_next+r mode "$mode_redshift"
set $mode_redshift Set colour temperature: (a)uto, (r)eset, (2)500K, (3)000K, (4)000K, (5)000K
set $kill_redshift pkill -9 redshift;
mode "$mode_redshift" {
    bindsym a exec --no-startup-id "$kill_redshift redshift -P -t 5000:4000", mode "default"
    bindsym r exec --no-startup-id "$kill_redshift redshift -x", mode "default"
    bindsym 2 exec --no-startup-id "$kill_redshift redshift -P -O 2500", mode "default"
    bindsym 3 exec --no-startup-id "$kill_redshift redshift -P -O 3000", mode "default"
    bindsym 4 exec --no-startup-id "$kill_redshift redshift -P -O 4000", mode "default"
    bindsym 5 exec --no-startup-id "$kill_redshift redshift -P -O 5000", mode "default"

    # exit mode: "Enter" or "Escape"
    bindsym Return mode "default"
    bindsym Escape mode "default"
}

bar {
    i3bar_command i3bar
    position top
    mode hide
    modifier none
    workspace_buttons no
    tray_output none
}

## Start i3bar to display a workspace bar (plus the system information i3status if available)
#bar {
#    i3bar_command i3bar
#    status_command py3status -c ~/.i3status.conf
#    position bottom
#
### please set your primary output first. Example: 'xrandr --output eDP1 --primary'
##   tray_output primary
##   tray_output eDP1
#
#    bindsym button4 nop bindsym button5 nop
##   font xft:URWGothic-Book 11
#    strip_workspace_numbers no
#
#    colors {
#        #background #4a4a4a
#        background #000000
#        #statusline #F9FAF9
#        statusline $accent-bg
#        #separator  #454947
#        separator  $accent-bg
#
##                      border  backgr. text
#        focused_workspace  $accent-txt $accent-bg $accent-txt
#        active_workspace   #595B5B #353836 #FDF6E3
#        inactive_workspace #595B5B #283339 #EEE8D5
#        binding_mode       $accent-bg #2C2C2C #F9FAF9
#        urgent_workspace   $accent-bg #FDF6E3 #E5201D
#    }
#}

# hide/unhide i3status bar
bindsym $mod+Control+m bar mode toggle

#############################
### settings for i3-gaps: ###
#############################

# Set inner/outer gaps
gaps outer 8
gaps inner 0

# Additionally, you can issue commands with the following syntax. This is useful to bind keys to changing the gap size.
# gaps inner|outer current|all set|plus|minus <px>
# gaps inner all set 10
# gaps outer all plus 5

# Smart gaps (gaps used if only more than one container on the workspace)
smart_gaps off

set $mode_gaps Gaps: (o)uter, (i)nner, (h)orizontal, (v)ertical, (t)op, (r)ight, (b)ottom, (l)eft
set $mode_gaps_outer Outer Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_inner Inner Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_horiz Horizontal Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_verti Vertical Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_top Top Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_right Right Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_bottom Bottom Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_left Left Gaps: +|-|0 (local), Shift + +|-|0 (global)
bindsym $mod+Shift+g mode "$mode_gaps"

mode "$mode_gaps" {
        bindsym o      mode "$mode_gaps_outer"
        bindsym i      mode "$mode_gaps_inner"
        bindsym h      mode "$mode_gaps_horiz"
        bindsym v      mode "$mode_gaps_verti"
        bindsym t      mode "$mode_gaps_top"
        bindsym r      mode "$mode_gaps_right"
        bindsym b      mode "$mode_gaps_bottom"
        bindsym l      mode "$mode_gaps_left"
        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}

mode "$mode_gaps_outer" {
        bindsym plus  gaps outer current plus 5
        bindsym minus gaps outer current minus 5
        bindsym 0     gaps outer current set 0

        bindsym Shift+plus  gaps outer all plus 5
        bindsym Shift+minus gaps outer all minus 5
        bindsym Shift+0     gaps outer all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}
mode "$mode_gaps_inner" {
        bindsym plus  gaps inner current plus 5
        bindsym minus gaps inner current minus 5
        bindsym 0     gaps inner current set 0

        bindsym Shift+plus  gaps inner all plus 5
        bindsym Shift+minus gaps inner all minus 5
        bindsym Shift+0     gaps inner all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}
mode "$mode_gaps_horiz" {
        bindsym plus  gaps horizontal current plus 5
        bindsym minus gaps horizontal current minus 5
        bindsym 0     gaps horizontal current set 0

        bindsym Shift+plus  gaps horizontal all plus 5
        bindsym Shift+minus gaps horizontal all minus 5
        bindsym Shift+0     gaps horizontal all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}
mode "$mode_gaps_verti" {
        bindsym plus  gaps vertical current plus 5
        bindsym minus gaps vertical current minus 5
        bindsym 0     gaps vertical current set 0

        bindsym Shift+plus  gaps vertical all plus 5
        bindsym Shift+minus gaps vertical all minus 5
        bindsym Shift+0     gaps vertical all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}
mode "$mode_gaps_top" {
        bindsym plus  gaps top current plus 5
        bindsym minus gaps top current minus 5
        bindsym 0     gaps top current set 0

        bindsym Shift+plus  gaps top all plus 5
        bindsym Shift+minus gaps top all minus 5
        bindsym Shift+0     gaps top all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}
mode "$mode_gaps_right" {
        bindsym plus  gaps right current plus 5
        bindsym minus gaps right current minus 5
        bindsym 0     gaps right current set 0

        bindsym Shift+plus  gaps right all plus 5
        bindsym Shift+minus gaps right all minus 5
        bindsym Shift+0     gaps right all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}
mode "$mode_gaps_bottom" {
        bindsym plus  gaps bottom current plus 5
        bindsym minus gaps bottom current minus 5
        bindsym 0     gaps bottom current set 0

        bindsym Shift+plus  gaps bottom all plus 5
        bindsym Shift+minus gaps bottom all minus 5
        bindsym Shift+0     gaps bottom all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}
mode "$mode_gaps_left" {
        bindsym plus  gaps left current plus 5
        bindsym minus gaps left current minus 5
        bindsym 0     gaps left current set 0

        bindsym Shift+plus  gaps left all plus 5
        bindsym Shift+minus gaps left all minus 5
        bindsym Shift+0     gaps left all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
} 

DPI Scaling with .Xresource and Xft.dpi

You may want/need to change your DPI with i3.  With my setup(s), I've never had success setting DPI with xrandr --dpi (which is often suggested).  Instead, we can set the DPI directly by editing (or creating) ~/.Xresources.

You might need to experiment  to find a DPI value that works for you.  Create or edit .Xresources your preferred DPI by adding the following (in this example I've set my DPI to 88 dots per inch):

~/.Xresources
Xft.dpi: 88
Override Chromium / Chrome (DPI) scaling

Recently Chromium appears to be respecting the Xft.dpi setting (which previously it didn't).  My preferred DPI was a bit hard to see now in Chromium.  You can override this behaviour  by set setting the --force-device-scale-factor flag.

Create (or edit) the file ~/.config/chromium-flags.conf and add the following (with your preferred scaling factor):

If you use Chrome credit (or edit) ~/config.chrome-flags.conf instead. 

~/.config/chromium-flags.conf
--force-device-scale-factor=0.96

Restart your browser windows and it should now no longer be using the Xft.dpi setting.

Ricing Conky (numix theme)

I've also riced my Conky setup somewhat.  Most of these changes to are to match my theme and current shortcuts setup.  I have two conky configs: one for showing various system stats (like cpu, RAM, swap etc.) and one showing several keyboard shortcuts.  See below for screenshot of my current conky setup:

Let's start with the conky config files:

Conky (numix) theme for system stats (top right in image above)
conky.config = {
	alignment = 'top_right',
	background = true,
	cpu_avg_samples = 2,
	default_color = 'd3d3d3',
	color2 = '07eded',
	double_buffer = true,
	font = 'Bitstream Vera Sans:size=8',
	draw_shades = false,
	gap_x = 25,
	gap_y = 13,
	minimum_width = 200,
	no_buffers = true,
	own_window = true,
	own_window_type = 'override',
	own_window_transparent = true,
	update_interval = 1.0,
	use_xft = true,
}
conky.text = [[
${voffset 8}$color2${font Bitstream Vera Sans:size=16}${time %A}$font\
${voffset -8}$alignr$color${font Bitstream Vera Sans:size=38}${time %e}$font
$color${voffset -30}$color${font Bitstream Vera Sans:size=18}${time %b}$font\
${voffset -3} $color${font Bitstream Vera Sans:size=20}${time %Y}$font$color2$hr
#
${voffset 20}${goto 40}${color}CPU${font Bitstream Vera Sans:bold:size=8}$alignr$cpu%
${voffset 5}${goto 40}$font$color2${top name 1}$alignr$color${top cpu 1}%
${goto 40}$color2${top name 2}$alignr$color${top cpu 2}%
${goto 40}$color2${top name 3}$alignr$color${top cpu 3}%
${goto 40}$color2${top name 4}$alignr$color${top cpu 4}%
${goto 40}$color2${top name 5}$alignr$color${top cpu 5}%
#
${voffset 10}${goto 40}${color}RAM${font Bitstream Vera Sans:bold:size=8}$alignr$mem$font
${goto 40}${voffset 5}$color2${top_mem name 1}$alignr$color${top_mem mem_res 1}
${goto 40}$color2${top_mem name 2}$alignr$color${top_mem mem_res 2}
${goto 40}$color2${top_mem name 3}$alignr$color${top_mem mem_res 3}
${goto 40}$color2${top_mem name 4}$alignr$color${top_mem mem_res 4}
${goto 40}$color2${top_mem name 5}$alignr$color${top_mem mem_res 5}
#
${voffset 10}${goto 40}${color}Swap${font Bitstream Vera Sans:bold:size=8}$alignr${swap}/ ${swapfree}
${voffset 15}$font$alignr${execi 10000 awk -F= '/TION/ {print $2}' /etc/lsb-release |sed 's/"//g'} \
${execi 10000 awk -F= '/EASE=/ {printf $2" "} /NAME/ {print $2}' /etc/lsb-release}
${voffset 10}${color2}${alignr}${execi 1200 whoami}@${nodename}
${alignr}${color2}${font Bitstream Vera Sans:size=8}uptime: ${color}${uptime_short}
${voffset 5}${color2}${font Bitstream Vera Sans:size=8}${alignr}kernel: ${color}${kernel}
]]

Conky shortcuts conf (see lower left in image above)
conky.config = {
	alignment = 'bottom_left',
	background = true,
	cpu_avg_samples = 2,
	default_color = '07eded',
	color2 = 'd3d3d3',
	double_buffer = true,
	font = 'Bitstream Vera Sans:size=8',
	draw_shades = false,
	gap_x = 25,
	gap_y = 45,
	minimum_width = 200,
	no_buffers = true,
	own_window = true,
	own_window_type = 'override',
	own_window_transparent = true,
	update_interval = 1.0,
	use_xft = true,
}
conky.text = [[
${color2}mod = ${color}<alt>
${color2}mod_next = ${color}<super>

${color2}open new terminal - ${color}mod+Enter
${color2}open package-manager - ${color}mod_next+u
${color2}open browser - ${color}mod_next+i
${color2}open appfinder - ${color}mod_next+o
${color2}open putty - ${color}mod_next+p

${color2}rofi (launcher) - ${color}mod_next+d
${color2}rofi (windows) - ${color}mod_next+Tab
${color2}kill focused - ${color}mod+Shift+q

${color2}container layout (tabbed) - ${color}mod+w
${color2}container layout (horiz) - ${color}mod+q
${color2}container layout (vert) - ${color}mod+e
${color2}container layout (stck) - ${color}mod+s
${color2}split container (tabbed) - ${color}mod+c

${color2}focus windows - ${color}mod+[hjkl|wasd]
${color2}move windows - ${color}mod+shift+[hjkl|wasd]
${color2}move right - ${color}mod+x
${color2}move left - ${color}mod+z

${color2}switch to workspace 1-8 - ${color}mod+1-8
${color2}send to workspace 1-8 - ${color}mod+Alt+1-8
${color2}navigate workspaces - ${color}mod+Ctrl+[hjkl|wasd]

${color2}toggle floating - ${color}mod+Shift+Space
${color2}toggle sticky - ${color}mod+Cntrl+v
${color2}window opacity up[dn] - ${color}mod+Alt+[x|z]
${color2}window dim disable[enable] - ${color}mod+ctrl+shift+a

${color2}exit - ${color}mod+0
]]

My main i3 config file (see preceding section) expects these conky config files to be in ~/.config (you can place them anywhere really, you'll just need to update your i3 config file to point to them).

Ricing the (standard) i3 status bar

I usually also make modifications to the i3 status bar colours for the system stats.  User specific i3 status bar config is configured int he ~/.i3status.conf file.  Here's is mine, with several changes including:

  • default font colour change;
  • disk format change (showing decimal %used / %total);
  • added wlan ip address and ethernet ip address (these are hidden if not connected);
  • added battery %remaining time (next to %percentage)

Contents of my ~/.i3status.conf (for use with standard i3status)
# i3status configuration file.
# see "man i3status" for documentation.

# It is important that this file is edited as UTF-8.
# The following line should contain a sharp s:
# ß
# If the above line is not correctly displayed, fix your editor first!

general {
        colors = true
        interval = 5
        color_good = "#F9FAF9"
        color_bad = "#F9FAF9"
        color_degraded = "#DC322F"
}

order += "cpu_usage"
order += "disk /"
order += "wireless _first_"
order += "ethernet _first_"
order += "battery all"
order += "tztime local"

cpu_usage {
        format = " cpu  %usage "
}

disk "/" {
	prefix_type = decimal
	format = " ⛁ %percentage_used (U:%used, F:%free) "
}

wireless _first_ {
	# if you use %speed, i3status requires root privileges
        format_up = " wlan: %ip "
        format_down = ""
}

ethernet _first_ {
	# if you use %speed, i3status requires root privileges
        format_up = " eth: %ip "
        format_down = ""
}

battery all {
        # format = "%status %percentage %remaining %emptytime"
        format = " %status %percentage %remaining "
        format_down = "No battery"
        last_full_capacity = true
        integer_battery_capacity = true
        status_chr = "⚡"
        status_bat = "🔋"
        status_unk = ""
        status_full = "☻"
        low_threshold = 15
        threshold_type = time
}

tztime local {
        format = "%Y-%m-%d %H:%M:%S"
        #format = " %d.%m. %H:%M "
}

Using (and ricing) py3status instead of i3status

py3status is a python wrapper for i3status that provides a lot more features and extendability.  py3status gives more much control and provides some very cool modules.  First, you'll need to install py3status with:

sudo pacman -S py3status

Once, installed you'll need to modify your ~/.i3/config file and replace the status_command i3status directive with

status_command py3status -c ~/.i3status.conf

You'll notice that we use the same .i3status.conf file (which with py3status we can define some extra modules etc.). 

Before you can use my py3status config file, you'll need to install font-awesome fonts (4.7) - I had issues with version 5, but works well with v4:

yay -S ttf-font-awesome-4

Below is my config file, which looks like this:

and includes p3status modules for:

  • spotify;
  • current network rate (download / upload);
  • public ip address information (isp, city, country);
  • currently connected network (wifi ssid and local ip address);
  • battery (with font awesome icons);
  • countdown timer;

Contents of my ~/.i3status.conf (for use with py3status)
# i3status configuration file.
# see "man i3status" for documentation.

# It is important that this file is edited as UTF-8.
# The following line should contain a sharp s:
# ß
# If the above line is not correctly displayed, fix your editor first!

general {
        colors = true
        interval = 5
        #color_good = "#F9FAF9"
        #color_bad = "#F9FAF9"
        color_good = "#07eded"
        color_bad = "#07eded"
        color_degraded = "#DC322F"
}

order += "spotify"
order += "net_rate"
order += "whatismyip"
order += "wireless _first_"
order += "ethernet _first_"
order += "cpu_usage"
order += "disk /"
#order += "diskdata"
order += "timer"
order += "battery all"
#order += "battery_level"
order += "path_exists VPN"
order += "external_script"
order += "tztime local"

spotify {
	format = "( {artist} : {title})"
	format_down = ""
	format_stopped = ""
}

timer {
	format = ":{timer}"
	time = 3600
}

cpu_usage {
        format = " cpu  %usage "
}

disk "/" {
	prefix_type = decimal
	format = " ⛁ %percentage_used (U:%used, F:%free) "	
}

diskdata {
	disk = sda2
	prefix_type = decimal
	#format_space = "[\?min_length=5 {value:.2f}]"
	format = " ⛁ {used_percent}% (U:{used} GB, F:{free} GB) "
}

external_script {
    format = "{output}"
    script_path = "cat /sys/class/tty/tty0/active"
}

whatismyip {
	format = " 🖧 {isp}\|{city}\|{countryCode} ({ip}) "
	icon_on = "🖧"
	hide_when_offline = True
	url_geo = "http://ip-api.com/json"
}

wireless _first_ {
	# if you use %speed, i3status requires root privileges
        format_up = "  %essid (%ip) "
        format_down = ""
}

ethernet _first_ {
	# if you use %speed, i3status requires root privileges
        format_up = "  eth (%ip) "
        format_down = ""
}

net_rate {
	format_value = "[\?min_length=10 {value:.1f} {unit}]"
	si_units = "True"
	format = "{down}⇣ {up}⇡"
        interfaces_blacklist = "lo"
}

battery all {
        format = " %status %percentage (%remaining) %consumption "
        format_down = "No battery"
        last_full_capacity = true
        integer_battery_capacity = true
        status_chr = "⚡"
        status_bat = ""
        status_unk = ""
        status_full = ""
        low_threshold = 15
        threshold_type = time
}

battery_level {
	cache_timeout = 5
	measurement_mode = "acpi"
	hide_when_full = "True"
	hide_seconds = "True"
	blocks = ""
	color_charging = "#00ff00"
	format = " {icon} {percent}% ({time_remaining}) "
}

tztime local {
        format = "%Y-%m-%d %H:%M:%S"
        #format = " %d/%m %H:%M:%S"
}

path_exists VPN {
        format = "%title:tun0"
        format_down = ""
        color_good = "#00ff00"
        path = "/sys/class/net/tun0/dev_id"
}

Ricing dmenu

Along with the main i3 config file, there is also a config file dmenu (main application launcher in Mi3).  The appearance (colours etc.) are configured in the ~/.dmenurc file.  Here is my .dmenurc config file with colours that match my main i3 config:

Contents of my ~/.dmenurc
#
# ~/.dmenurc
#
 
## define the font for dmenu to be used
DMENU_FN="Noto-10.5"
 
## background colour for unselected menu-items
DMENU_NB="#4a4a4a"
 
## textcolour for unselected menu-items
DMENU_NF="#F9FAF9"
 
## background colour for selected menu-items
DMENU_SB="#eb564d"
 
## textcolour for selected menu-items
DMENU_SF="#F9FAF9"
 
## command for the terminal application to be used:
TERMINAL_CMD="terminal -e"
 
## export our variables
DMENU_OPTIONS="-fn $DMENU_FN -nb $DMENU_NB -nf $DMENU_NF -sf $DMENU_SF -sb $DMENU_SB"

Ricing rofi (to match my theming)

If you use rofi, as I do (see my .i3/config above), you can also change it's theme.  There are a very nice selection of themes included with rofi.  You can change theme by running the following from your terminal

rofi-theme-selector

Theme files can be found in usr/share/rofi/themes.

I really liked the lb.rasi theme (which is included with rofi).  However, it didn't quite match the colours of my current theme.  I made a few subtle changes to this theme (only changed colours to match what I like).  Below is the resulting file, which should be placed in the rofi theme folder (see above).

Contents of my /usr/share/rofi/themes/lb-numix.rasi
/**
 * ROFI Color theme
 * User: JT (adpated from lb by Qball)
 * Copyright: Dave Davenport
 */
 
* {
    selected-normal-foreground:  @foreground;
    foreground:                  #FFFFFF;
    normal-foreground:           @foreground;
    alternate-normal-background: rgba ( 255, 255, 255, 7 % );
    red:                         rgba ( 220, 50, 47, 100 % );
    selected-urgent-foreground:  rgba ( 51, 51, 51, 100 % );
    blue:                        rgba ( 38, 139, 210, 100 % );
    urgent-foreground:           rgba ( 255, 153, 153, 100 % );
    alternate-urgent-background: rgba ( 255, 255, 255, 7 % );
    active-foreground:           @bordercolor;
    lightbg:                     rgba ( 238, 232, 213, 100 % );
    selected-active-foreground:  @foreground;
    alternate-active-background: rgba ( 255, 255, 255, 7 % );
    background:                  rgba ( 51, 51, 51, 93 % );
    bordercolor:                 rgba ( 214, 65, 97, 100 % );
    alternate-normal-foreground: @foreground;
    normal-background:           rgba ( 0, 0, 0, 0 % );
    lightfg:                     rgba ( 88, 104, 117, 100 % );
    selected-normal-background:  @bordercolor;
    border-color:                @bordercolor;
    spacing:                     2;
    separatorcolor:              @bordercolor;
    urgent-background:           rgba ( 0, 0, 0, 0 % );
    selected-urgent-background:  rgba ( 255, 153, 153, 100 % );
    alternate-urgent-foreground: @urgent-foreground;
    background-color:            rgba ( 0, 0, 0, 0 % );
    alternate-active-foreground: @active-foreground;
    active-background:           rgba ( 0, 0, 0, 0 % );
    selected-active-background:  @bordercolor;
}
#window {
    background-color: @background;
    border:           1;
    padding:          5;
}
#mainbox {
    border:  0;
    padding: 0;
}
#message {
    border:       1px dash 0px 0px ;
    border-color: @separatorcolor;
    padding:      1px ;
}
#textbox {
    text-color: @foreground;
}
#listview {
    fixed-height: 0;
    border:       2px solid 0px 0px ;
    border-color: @separatorcolor;
    spacing:      2px ;
    scrollbar:    true;
    padding:      2px 0px 0px ;
}
#element {
    border:  0;
    padding: 1px;
}
#element.normal.normal {
    background-color: @normal-background;
    text-color:       @normal-foreground;
}
#element.normal.urgent {
    background-color: @urgent-background;
    text-color:       @urgent-foreground;
}
#element.normal.active {
    background-color: @active-background;
    text-color:       @active-foreground;
}
#element.selected.normal {
    background-color: @selected-normal-background;
    text-color:       @selected-normal-foreground;
}
#element.selected.urgent {
    background-color: @selected-urgent-background;
    text-color:       @selected-urgent-foreground;
}
#element.selected.active {
    background-color: @selected-active-background;
    text-color:       @selected-active-foreground;
}
#element.alternate.normal {
    background-color: @alternate-normal-background;
    text-color:       @alternate-normal-foreground;
}
#element.alternate.urgent {
    background-color: @alternate-urgent-background;
    text-color:       @alternate-urgent-foreground;
}
#element.alternate.active {
    background-color: @alternate-active-background;
    text-color:       @alternate-active-foreground;
}
#scrollbar {
    width:        4px ;
    border:       0;
    handle-width: 8px ;
    padding:      0;
    handle-color: @bordercolor;
}
#sidebar {
    border:       2px dash 0px 0px ;
    border-color: @separatorcolor;
}
#button.selected {
    background-color: @selected-normal-background;
    text-color:       @selected-normal-foreground;
}
#inputbar {
    spacing:    0;
    text-color: @normal-foreground;
    padding:    1px ;
}
#case-indicator {
    spacing:    0;
    text-color: @normal-foreground;
}
#entry {
    spacing:    0;
    text-color: @normal-foreground;
}
#prompt {
    spacing:    0;
    text-color: @normal-foreground;
}
#inputbar {
    children:   [ prompt,textbox-prompt-colon,entry,case-indicator ];
}
#textbox-prompt-colon {
    expand:     false;
    str:        ":";
    margin:     0px 0.3em 0em 0em ;
    text-color: @normal-foreground;
}

Ricing notifications (dunst)

You can also modify the look of the system notifications.  Configure colours etc. in ~/.config/dunst/dunstrc.  Here's a few small modifications to my dunstrc file (to match my theme):

Modifications to ~/.config/dunst/dunstrc
[global]
    frame_width = 3
    frame_color = "#eb564d"
    
    font = Noto Sans 10
    
    # Allow a small subset of html markup:
    #   <b>bold</b>
    #   <i>italic</i>
    #   <s>strikethrough</s>
    #   <u>underline</u>
    # 
    # For a complete reference see
    # <http://developer.gnome.org/pango/stable/PangoMarkupFormat.html>.
    # If markup is not allowed, those tags will be stripped out of the
    # message.
    markup = yes
    
    # The format of the message.  Possible variables are:
    #   %a  appname
    #   %s  summary
    #   %b  body
    #   %i  iconname (including its path)
    #   %I  iconname (without its path)
    #   %p  progress value if set ([  0%] to [100%]) or nothing
    # Markup is allowed
    format = "%s %p\n%b"
    
    # Sort messages by urgency.
    sort = yes
    
    # Show how many messages are currently hidden (because of geometry).
    indicate_hidden = yes
    
    # Alignment of message text.
    # Possible values are "left", "center" and "right".
    alignment = left
    
    # The frequency with wich text that is longer than the notification
    # window allows bounces back and forth.
    # This option conflicts with "word_wrap".
    # Set to 0 to disable.
    bounce_freq = 5

    
    # Show age of message if message is older than show_age_threshold
    # seconds.
    # Set to -1 to disable.
    show_age_threshold = 60
    
    # Split notifications into multiple lines if they don't fit into
    # geometry.
    word_wrap = no
    
    # Ignore newlines '\n' in notifications.
    ignore_newline = no
    
    
    # The geometry of the window:
    #   [{width}]x{height}[+/-{x}+/-{y}]
    # The geometry of the message window.
    # The height is measured in number of notifications everything else
    # in pixels.  If the width is omitted but the height is given
    # ("-geometry x2"), the message window expands over the whole screen
    # (dmenu-like).  If width is 0, the window expands to the longest
    # message displayed.  A positive x is measured from the left, a
    # negative from the right side of the screen.  Y is measured from
    # the top and down respectevly.
    # The width can be negative.  In this case the actual width is the
    # screen width minus the width defined in within the geometry option.
    geometry = "0x4-25+25"
    
    # Shrink window if it's smaller than the width.  Will be ignored if
    # width is 0.
    shrink = yes
    
    # The transparency of the window.  Range: [0; 100].
    # This option will only work if a compositing windowmanager is
    # present (e.g. xcompmgr, compiz, etc.).
    transparency = 15
    
    # Don't remove messages, if the user is idle (no mouse or keyboard input)
    # for longer than idle_threshold seconds.
    # Set to 0 to disable.
    # default 120
    idle_threshold = 120 
    
    # Which monitor should the notifications be displayed on.
    monitor = 0
    
    # Display notification on focused monitor.  Possible modes are:
    #   mouse: follow mouse pointer
    #   keyboard: follow window with keyboard focus
    #   none: don't follow anything
    # 
    # "keyboard" needs a windowmanager that exports the
    # _NET_ACTIVE_WINDOW property.
    # This should be the case for almost all modern windowmanagers.
    # 
    # If this option is set to mouse or keyboard, the monitor option
    # will be ignored.
    follow = mouse
    
    # Should a notification popped up from history be sticky or timeout
    # as if it would normally do.
    sticky_history = yes
    
    # Maximum amount of notifications kept in history
    history_length = 20
    
    # Display indicators for URLs (U) and actions (A).
    show_indicators = yes
    
    # The height of a single line.  If the height is smaller than the
    # font height, it will get raised to the font height.
    # This adds empty space above and under the text.
    line_height = 0
    
    # Draw a line of "separator_height" pixel height between two
    # notifications.
    # Set to 0 to disable.
    separator_height = 1
    
    # Padding between text and separator.
    # padding = 8
    padding = 8
    
    # Horizontal padding.
    horizontal_padding = 10
    
    # Define a color for the separator.
    # possible values are:
    #  * auto: dunst tries to find a color fitting to the background;
    #  * foreground: use the same color as the foreground;
    #  * frame: use the same color as the frame;
    #  * anything else will be interpreted as a X color.
    separator_color = #263238
    
    # Print a notification on startup.
    # This is mainly for error detection, since dbus (re-)starts dunst
    # automatically after a crash.
    startup_notification = false
    
    # dmenu path.
    dmenu = /usr/bin/dmenu -p dunst:
    
    # Browser for opening urls in context menu.
    browser = palemoon

    # Align icons left/right/off
    icon_position = left

    # Paths to default icons.
    icon_path = /usr/share/icons/Adwaita/16x16/status/:/usr/share/icons/Adwaita/16x16/devices/

    # Limit icons size.
    max_icon_size=128

[shortcuts]

    # Shortcuts are specified as [modifier+][modifier+]...key
    # Available modifiers are "ctrl", "mod1" (the alt-key), "mod2",
    # "mod3" and "mod4" (windows-key).
    # Xev might be helpful to find names for keys.
    
    # Close notification.
    #close = mod1+space
    
    # Close all notifications.
    # close_all = ctrl+shift+space
    #close_all = ctrl+mod1+space

    # Redisplay last message(s).
    # On the US keyboard layout "grave" is normally above TAB and left
    # of "1".
    #history = ctrl+mod4+h 
    
    # Context menu.
    #context = ctrl+mod1+c

[urgency_low]
    # IMPORTANT: colors have to be defined in quotation marks.
    # Otherwise the "#" and following would be interpreted as a comment.
    background = "#4a4a4a"
    foreground = "#F9FAF9"
    timeout = 3

[urgency_normal]
    background = "#4a4a4a"
    foreground = "#F9FAF9"
    timeout = 3

[urgency_critical]
    background = "#D62929"
    foreground = "#F9FAF9"
    timeout = 0


# Every section that isn't one of the above is interpreted as a rules to
# override settings for certain messages.
# Messages can be matched by "appname", "summary", "body", "icon", "category",
# "msg_urgency" and you can override the "timeout", "urgency", "foreground",
# "background", "new_icon" and "format".
# Shell-like globbing will get expanded.
#
# SCRIPTING
# You can specify a script that gets run when the rule matches by
# setting the "script" option.
# The script will be called as follows:
#   script appname summary body icon urgency
# where urgency can be "LOW", "NORMAL" or "CRITICAL".
# 
# NOTE: if you don't want a notification to be displayed, set the format
# to "".
# NOTE: It might be helpful to run dunst -print in a terminal in order
# to find fitting options for rules.

#[espeak]
#    summary = "*"
#    script = dunst_espeak.sh

#[script-test]
#    summary = "*script*"
#    script = dunst_test.sh

#[ignore]
#    # This notification will not be displayed
#    summary = "foobar"
#    format = ""

#[signed_on]
#    appname = Pidgin
#    summary = "*signed on*"
#    urgency = low
#
#[signed_off]
#    appname = Pidgin
#    summary = *signed off*
#    urgency = low
#
#[says]
#    appname = Pidgin
#    summary = *says*
#    urgency = critical
#
#[twitter]
#    appname = Pidgin
#    summary = *twitter.com*
#    urgency = normal
#
#[Claws Mail]
#    appname = claws-mail
#    category = email.arrived
#    urgency = normal
#    background = "#2F899E"
#    foreground = "#FFA247"
#
#[mute.sh]
#     appname = mute
#     category = mute.sound
#     script = mute.sh
#
#[JDownloader]
#    appname = JDownloader
#    category = JD
#    background = "#FFA247"
#    foreground = "#FFFFFF"
#
#[newsbeuter]
#    summary = *Feeds*
#    background = "#A8EB41"
#    foreground = "#FFFFFF"
#
[irc]
        appname = weechat
        timeout = 0
        background = "#0033bb"
        foreground = "#dddddd"
#
[weechat hl]
     appname = weechat
     category = weechat.HL
     background = "#FF5C47"
     foreground = "#FFFFFF"
#
[weechat pn]
     appname = weechat
     category = weechat.PM
     background = "#D53B84"
     foreground = "#FFFFFF"
#
#[CMUS]
#    appname = CMUS
#    category = cmus
#    background = "#6C4AB7"
#    foreground = "#FFE756"
#
#
#     background = "#30AB70"
#     foreground = "#F67245"
#
# vim: ft=cfg

I've disabled the default dunst shortcuts as they interfered with some of my i3 config bindsyms.

Ricing alttab

Although I do like the way i3 approaches window switching - I do miss the speed of alt-tabbing for switching between the last focused application and the current application (and doing so often).  For this I use the very nice alttab.  It's in the AUR so once you've enabled AUR (and installed something like yay) you can do:

sudo yay -S alttab-git

You can customise the look of alttab by changing the background, foreground and frame colour.  Below is the settings that match my numix theme.  Add the following to your ~/.i3/config:

exec --no-startup-id alttab -fg "#d58681" -bg "#4a4a4a" -frame "#eb564d" -t 128x150 -i 127x64

I also like to add a bit of transparency to my alttab.  You can do this by adding a rule for alttab to the opacity-rule array definition as seen in my picom.conf:

#################################
#             Shadows           #
#################################


# Enabled client-side shadows on windows. Note desktop windows
# (windows with '_NET_WM_WINDOW_TYPE_DESKTOP') never get shadow,
# unless explicitly requested using the wintypes option.
#
# shadow = false

# The blur radius for shadows, in pixels. (defaults to 12)
# shadow-radius = 12

# The opacity of shadows. (0.0 - 1.0, defaults to 0.75)
# shadow-opacity = .75

# The left offset for shadows, in pixels. (defaults to -15)
# shadow-offset-x = -15

# The top offset for shadows, in pixels. (defaults to -15)
# shadow-offset-y = -15

# Red color value of shadow (0.0 - 1.0, defaults to 0).
# shadow-red = 0

# Green color value of shadow (0.0 - 1.0, defaults to 0).
# shadow-green = 0

# Blue color value of shadow (0.0 - 1.0, defaults to 0).
# shadow-blue = 0

# Hex string color value of shadow (#000000 - #FFFFFF, defaults to #000000). This option will override options set shadow-(red/green/blue)
# shadow-color = "#000000"

# Specify a list of conditions of windows that should have no shadow.
#
# examples:
#   shadow-exclude = "n:e:Notification";
#
# shadow-exclude = []
shadow-exclude = [
    "! name~=''",
    "name = 'Notification'",
    "name = 'Plank'",
    "name = 'Docky'",
    "name = 'Kupfer'",
    "name = 'xfce4-notifyd'",
    "name = 'cpt_frame_window'",
    "name *= 'VLC'",
    "name *= 'compton'",
    "name *= 'picom'",
    "name *= 'Chromium'",
    "name *= 'Chrome'",
    "class_g = 'Firefox' && argb",
    "class_g = 'Conky'",
    "class_g = 'Kupfer'",
    "class_g = 'Synapse'",
    "class_g ?= 'Notify-osd'",
    "class_g ?= 'Cairo-dock'",
    "class_g ?= 'Xfce4-notifyd'",
    "class_g ?= 'Xfce4-power-manager'",
    # disables shadows for hidden windows
    "_GTK_FRAME_EXTENTS@:c",
    "_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'",
    # disables shadows on sticky windows:
    "_NET_WM_STATE@:32a *= '_NET_WM_STATE_STICKY'",
    # disables shadows on i3 frames
    "class_g ?= 'i3-frame'",
    # workaround for conky until it provides window properties:
    "override_redirect = 1 && !WM_CLASS@:s"
];

# Specify a list of conditions of windows that should have no shadow painted over, such as a dock window.
# clip-shadow-above = []

# Specify a X geometry that describes the region in which shadow should not
# be painted in, such as a dock window region. Use
#    shadow-exclude-reg = "x10+0+0"
# for example, if the 10 pixels on the bottom of the screen should not have shadows painted on.
#
# shadow-exclude-reg = ""

# Crop shadow of a window fully on a particular Xinerama screen to the screen.
# xinerama-shadow-crop = false


#################################
#           Fading              #
#################################


# Fade windows in/out when opening/closing and when opacity changes,
#  unless no-fading-openclose is used.
# fading = false
fading = true;

# Opacity change between steps while fading in. (0.01 - 1.0, defaults to 0.028)
# fade-in-step = 0.028
fade-in-step = 0.03;

# Opacity change between steps while fading out. (0.01 - 1.0, defaults to 0.03)
# fade-out-step = 0.03
fade-out-step = 0.03;

# The time between steps in fade step, in milliseconds. (> 0, defaults to 10)
# fade-delta = 10
fade-delta = 4;

# Specify a list of conditions of windows that should not be faded.
# fade-exclude = []

# Do not fade on window open/close.
# no-fading-openclose = false

# Do not fade destroyed ARGB windows with WM frame. Workaround of bugs in Openbox, Fluxbox, etc.
# no-fading-destroyed-argb = false


#################################
#   Transparency / Opacity      #
#################################


# Opacity of inactive windows. (0.1 - 1.0, defaults to 1.0)
# inactive-opacity = 1

# Opacity of window titlebars and borders. (0.1 - 1.0, disabled by default)
# frame-opacity = 1.0

# Let inactive opacity set by -i override the '_NET_WM_OPACITY' values of windows.
# inactive-opacity-override = true

# Default opacity for active windows. (0.0 - 1.0, defaults to 1.0)
# active-opacity = 1.0

# Dim inactive windows. (0.0 - 1.0, defaults to 0.0)
# inactive-dim = 0.0

# Specify a list of conditions of windows that should never be considered focused.
# focus-exclude = []
focus-exclude = [ "class_g = 'Cairo-clock'" ];

# Use fixed inactive dim value, instead of adjusting according to window opacity.
# inactive-dim-fixed = 1.0

# Specify a list of opacity rules, in the format `PERCENT:PATTERN`,
# like `50:name *= "Firefox"`. picom-trans is recommended over this.
# Note we don't make any guarantee about possible conflicts with other
# programs that set '_NET_WM_WINDOW_OPACITY' on frame or client windows.
# example:
#    opacity-rule = [ "80:class_g = 'URxvt'" ];
#
opacity-rule = [
    "90:name = 'alttab'",
    "80:name = 'i3-overview'",
    # no opacity on sticky windows
    "99:_NET_WM_STATE@:32a *= '_NET_WM_STATE_STICKY'"
];


#################################
#           Corners             #
#################################

# Sets the radius of rounded window corners. When > 0, the compositor will
# round the corners of windows. Does not interact well with
# `transparent-clipping`.
corner-radius = 0;

# Exclude conditions for rounded corners.
rounded-corners-exclude = [
  "window_type = 'dock'",
  "window_type = 'desktop'"
];


#################################
#     Background-Blurring       #
#################################


# Parameters for background blurring, see the *BLUR* section for more information.
# blur-method =
# blur-size = 12
#
# blur-deviation = false
#
# blur-strength = 5

# Blur background of semi-transparent / ARGB windows.
# Bad in performance, with driver-dependent behavior.
# The name of the switch may change without prior notifications.
#
# blur-background = false

# Blur background of windows when the window frame is not opaque.
# Implies:
#    blur-background
# Bad in performance, with driver-dependent behavior. The name may change.
#
# blur-background-frame = false

# Use fixed blur strength rather than adjusting according to window opacity.
# blur-background-fixed = false

# Specify the blur convolution kernel, with the following format:
# example:
#   blur-kern = "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
#
# blur-kern = ""
blur-kern = "3x3box";

# Exclude conditions for background blur.
# blur-background-exclude = []
blur-background-exclude = [
  "window_type = 'dock'",
  "window_type = 'desktop'",
  "_GTK_FRAME_EXTENTS@:c"
];


#################################
#       Colour-inversion        #
#################################

# Specify list of windows or x flag to that will be colour inverted.
invert-color-include = [
    "INVERT_FLAG@:8c"
];


#################################
#       General Settings        #
#################################

# Daemonize process. Fork to background after initialization. Causes issues with certain (badly-written) drivers.
# daemon = false

# Specify the backend to use: `xrender`, `glx`, or `xr_glx_hybrid`.
# `xrender` is the default one.
#
backend = "glx";

# Enable/disable VSync.
# vsync = false
vsync = true;

# Enable remote control via D-Bus. See the *D-BUS API* section below for more details.
# dbus = false

# Try to detect WM windows (a non-override-redirect window with no
# child that has 'WM_STATE') and mark them as active.
#
# mark-wmwin-focused = false
mark-wmwin-focused = true;

# Mark override-redirect windows that doesn't have a child window with 'WM_STATE' focused.
# mark-ovredir-focused = false
mark-ovredir-focused = true;

# Try to detect windows with rounded corners and don't consider them
# shaped windows. The accuracy is not very high, unfortunately.
#
# detect-rounded-corners = false

# Detect '_NET_WM_OPACITY' on client windows, useful for window managers
# not passing '_NET_WM_OPACITY' of client windows to frame windows.
#
# detect-client-opacity = false
detect-client-opacity = true;

# Specify refresh rate of the screen. If not specified or 0, picom will
# try detecting this with X RandR extension.
#
# refresh-rate = 60
refresh-rate = 0;

# Use EWMH '_NET_ACTIVE_WINDOW' to determine currently focused window,
# rather than listening to 'FocusIn'/'FocusOut' event. Might have more accuracy,
# provided that the WM supports it.
#
# use-ewmh-active-win = false
use-ewmh-active-win = true;

# Unredirect all windows if a full-screen opaque window is detected,
# to maximize performance for full-screen windows. Known to cause flickering
# when redirecting/unredirecting windows.
#
# unredir-if-possible = false

# Delay before unredirecting the window, in milliseconds. Defaults to 0.
# unredir-if-possible-delay = 0

# Conditions of windows that shouldn't be considered full-screen for unredirecting screen.
# unredir-if-possible-exclude = []

# Use 'WM_TRANSIENT_FOR' to group windows, and consider windows
# in the same group focused at the same time.
#
# detect-transient = false
detect-transient = true;

# Use 'WM_CLIENT_LEADER' to group windows, and consider windows in the same
# group focused at the same time. This usually means windows from the same application
# will be considered focused or unfocused at the same time.
# 'WM_TRANSIENT_FOR' has higher priority if detect-transient is enabled, too.
#
# detect-client-leader = false
detect-client-leader = true;

# Resize damaged region by a specific number of pixels.
# A positive value enlarges it while a negative one shrinks it.
# If the value is positive, those additional pixels will not be actually painted
# to screen, only used in blur calculation, and such. (Due to technical limitations,
# with use-damage, those pixels will still be incorrectly painted to screen.)
# Primarily used to fix the line corruption issues of blur,
# in which case you should use the blur radius value here
# (e.g. with a 3x3 kernel, you should use `--resize-damage 1`,
# with a 5x5 one you use `--resize-damage 2`, and so on).
# May or may not work with *--glx-no-stencil*. Shrinking doesn't function correctly.
#
# resize-damage = 1

# Specify a list of conditions of windows that should be painted with inverted color.
# Resource-hogging, and is not well tested.
#
# invert-color-include = []

# GLX backend: Avoid using stencil buffer, useful if you don't have a stencil buffer.
# Might cause incorrect opacity when rendering transparent content (but never
# practically happened) and may not work with blur-background.
# My tests show a 15% performance boost. Recommended.
#
# glx-no-stencil = false

# GLX backend: Avoid rebinding pixmap on window damage.
# Probably could improve performance on rapid window content changes,
# but is known to break things on some drivers (LLVMpipe, xf86-video-intel, etc.).
# Recommended if it works.
#
# glx-no-rebind-pixmap = false

# Disable the use of damage information.
# This cause the whole screen to be redrawn everytime, instead of the part of the screen
# has actually changed. Potentially degrades the performance, but might fix some artifacts.
# The opposing option is use-damage
#
# no-use-damage = false
use-damage = true;

# Use X Sync fence to sync clients' draw calls, to make sure all draw
# calls are finished before picom starts drawing. Needed on nvidia-drivers
# with GLX backend for some users.
#
# xrender-sync-fence = false
xrender-sync-fence = true;

# GLX backend: Use specified GLSL fragment shader for rendering window contents.
# See `compton-default-fshader-win.glsl` and `compton-fake-transparency-fshader-win.glsl`
# in the source tree for examples.
#
# glx-fshader-win = ""

# Force all windows to be painted with blending. Useful if you
# have a glx-fshader-win that could turn opaque pixels transparent.
#
# force-win-blend = false

# Do not use EWMH to detect fullscreen windows.
# Reverts to checking if a window is fullscreen based only on its size and coordinates.
#
# no-ewmh-fullscreen = false

# Dimming bright windows so their brightness doesn't exceed this set value.
# Brightness of a window is estimated by averaging all pixels in the window,
# so this could comes with a performance hit.
# Setting this to 1.0 disables this behaviour. Requires --use-damage to be disabled. (default: 1.0)
#
# max-brightness = 1.0

# Make transparent windows clip other windows like non-transparent windows do,
# instead of blending on top of them.
#
# transparent-clipping = false

# Set the log level. Possible values are:
#  "trace", "debug", "info", "warn", "error"
# in increasing level of importance. Case doesn't matter.
# If using the "TRACE" log level, it's better to log into a file
# using *--log-file*, since it can generate a huge stream of logs.
#
# log-level = "debug"
log-level = "warn";

# Set the log file.
# If *--log-file* is never specified, logs will be written to stderr.
# Otherwise, logs will to written to the given file, though some of the early
# logs might still be written to the stderr.
# When setting this option from the config file, it is recommended to use an absolute path.
#
# log-file = "/path/to/your/log/file"

# Show all X errors (for debugging)
# show-all-xerrors = false

# Write process ID to a file.
# write-pid-path = "/path/to/your/log/file"

# Window type settings
#
# 'WINDOW_TYPE' is one of the 15 window types defined in EWMH standard:
#     "unknown", "desktop", "dock", "toolbar", "menu", "utility",
#     "splash", "dialog", "normal", "dropdown_menu", "popup_menu",
#     "tooltip", "notification", "combo", and "dnd".
#
# Following per window-type options are available: ::
#
#   fade, shadow:::
#     Controls window-type-specific shadow and fade settings.
#
#   opacity:::
#     Controls default opacity of the window type.
#
#   focus:::
#     Controls whether the window of this type is to be always considered focused.
#     (By default, all window types except "normal" and "dialog" has this on.)
#
#   full-shadow:::
#     Controls whether shadow is drawn under the parts of the window that you
#     normally won't be able to see. Useful when the window has parts of it
#     transparent, and you want shadows in those areas.
#
#   clip-shadow-above:::
#     Controls wether shadows that would have been drawn above the window should
#     be clipped. Useful for dock windows that should have no shadow painted on top.
#
#   redir-ignore:::
#     Controls whether this type of windows should cause screen to become
#     redirected again after been unredirected. If you have unredir-if-possible
#     set, and doesn't want certain window to cause unnecessary screen redirection,
#     you can set this to `true`.
#
wintypes:
{
  tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; full-shadow = false; };
  dock = { shadow = false; clip-shadow-above = true; }
  dnd = { shadow = false; }
  #popup_menu = { opacity = 0.8; }
  #dropdown_menu = { opacity = 0.8; }
};

Resulting alttab settings that match my theme:

Dim non-active windows instead of applying transparency (and implement per window dim enable/disable shortcuts)

I prefer visual identification of non-active windows by dimming rather than transparency.  By default, Manjaro i3 uses a non-active window transparency as a way to help visually identify active/non-active windows.  This works quite well, but I find this adds to the "visual noise" in a busy i3 session.

The following approach replaces the default inactive window transparency with picom dim rules.  We'll also cover how modify dimming on a per window basis via a keyboard shortcuts (occasionally want to disable the default dimming on a window by window basis).

First, let's disable picom's inactive-opacity setting.  Your opacity settings in picom.conf might look something like this:

inactive-opacity = 1;
active-opacity = 1;
frame-opacity = 1;
inactive-opacity-override = false;
opacity-rule = [
    "80:class_g = 'copyq'",
    "90:name = 'alttab'",
    # no opacity on sticky windows
    "99:_NET_WM_STATE@:32a *= '_NET_WM_STATE_STICKY'"
];

We want to make sure that inactive-opacity is set to 1 (or disabled) and active-opacity is also set to 1.  I've also kept a few opacity=rule rules that I want to still apply to several window types.  Note the last rule above - it simply disables transparency for sticky windows (another i3 concept which allows to keep a window showing/pinned on all workspaces).

Now, let's setup default dim settings.  We'll do so by adding the following settings:

# Dim inactive windows. (0.0 - 1.0)
inactive-dim = 0.2;
...
focus-exclude = [
  "ANTIDIM_FLAG@:8c",
  "_NET_WM_STATE@:32a *= '_NET_WM_STATE_STICKY'"
];

Note the focus-exclude rule array.  This defines rules for NOT applying dim on window types. 

Notice the rule ANTIDIM_FLAG@:8c, we'll use this to NOT applying dimming by window property (which we'll apply to selected windows via an i3 keyboard shortcut).

We can apply arbitrary window properties on selected windows.  Picom will respect these rules (by property).  The ANTIDIM_FLAG@:8c rules above (in the focus-exclude array is an example of this).  To apply/remove this window property on a selected window add the following bindsyms to your i3.conf:

# window dimming enable or disable (uses xdotool and xprop to set a anti-dim flag, which picom recognises in focus-exclude array) 
bindsym $mod+Mod1+a exec xprop -id $(xdotool getactivewindow) -f ANTIDIM_FLAG 8c -set ANTIDIM_FLAG 1; exec notify-send 'anti-dim set on window'
bindsym $mod+Mod1+d exec xprop -id $(xdotool getactivewindow) -remove ANTIDIM_FLAG; exec notify-send 'dim set on window'

For the above shortcuts to work, you'll need to install xdotool and xprop.

The above shortcuts will enable the ANTIDIM property for the currently selected window (which will disable dimming on said window) or disable the ANTIDIM property (which will then respect the default dim settings defined above).

For reference here is my ~/.config/picom.conf

~/.config/picom.conf
#################################
#             Shadows           #
#################################


# Enabled client-side shadows on windows. Note desktop windows
# (windows with '_NET_WM_WINDOW_TYPE_DESKTOP') never get shadow,
# unless explicitly requested using the wintypes option.
#
# shadow = false

# The blur radius for shadows, in pixels. (defaults to 12)
# shadow-radius = 12

# The opacity of shadows. (0.0 - 1.0, defaults to 0.75)
# shadow-opacity = .75

# The left offset for shadows, in pixels. (defaults to -15)
# shadow-offset-x = -15

# The top offset for shadows, in pixels. (defaults to -15)
# shadow-offset-y = -15

# Red color value of shadow (0.0 - 1.0, defaults to 0).
# shadow-red = 0

# Green color value of shadow (0.0 - 1.0, defaults to 0).
# shadow-green = 0

# Blue color value of shadow (0.0 - 1.0, defaults to 0).
# shadow-blue = 0

# Hex string color value of shadow (#000000 - #FFFFFF, defaults to #000000). This option will override options set shadow-(red/green/blue)
# shadow-color = "#000000"

# Specify a list of conditions of windows that should have no shadow.
#
# examples:
#   shadow-exclude = "n:e:Notification";
#
# shadow-exclude = []
shadow-exclude = [
    "! name~=''",
    "name = 'Notification'",
    "name = 'Plank'",
    "name = 'Docky'",
    "name = 'Kupfer'",
    "name = 'xfce4-notifyd'",
    "name = 'cpt_frame_window'",
    "name *= 'VLC'",
    "name *= 'compton'",
    "name *= 'picom'",
    "name *= 'Chromium'",
    "name *= 'Chrome'",
    "class_g = 'Firefox' && argb",
    "class_g = 'Conky'",
    "class_g = 'Kupfer'",
    "class_g = 'Synapse'",
    "class_g ?= 'Notify-osd'",
    "class_g ?= 'Cairo-dock'",
    "class_g ?= 'Xfce4-notifyd'",
    "class_g ?= 'Xfce4-power-manager'",
    # disables shadows for hidden windows
    "_GTK_FRAME_EXTENTS@:c",
    "_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'",
    # disables shadows on sticky windows:
    "_NET_WM_STATE@:32a *= '_NET_WM_STATE_STICKY'",
    # disables shadows on i3 frames
    "class_g ?= 'i3-frame'",
    # workaround for conky until it provides window properties:
    "override_redirect = 1 && !WM_CLASS@:s"
];

# Specify a list of conditions of windows that should have no shadow painted over, such as a dock window.
# clip-shadow-above = []

# Specify a X geometry that describes the region in which shadow should not
# be painted in, such as a dock window region. Use
#    shadow-exclude-reg = "x10+0+0"
# for example, if the 10 pixels on the bottom of the screen should not have shadows painted on.
#
# shadow-exclude-reg = ""

# Crop shadow of a window fully on a particular Xinerama screen to the screen.
# xinerama-shadow-crop = false


#################################
#           Fading              #
#################################


# Fade windows in/out when opening/closing and when opacity changes,
#  unless no-fading-openclose is used.
# fading = false
fading = true;

# Opacity change between steps while fading in. (0.01 - 1.0, defaults to 0.028)
# fade-in-step = 0.028
fade-in-step = 0.03;

# Opacity change between steps while fading out. (0.01 - 1.0, defaults to 0.03)
# fade-out-step = 0.03
fade-out-step = 0.03;

# The time between steps in fade step, in milliseconds. (> 0, defaults to 10)
# fade-delta = 10
fade-delta = 4;

# Specify a list of conditions of windows that should not be faded.
# fade-exclude = []

# Do not fade on window open/close.
# no-fading-openclose = false

# Do not fade destroyed ARGB windows with WM frame. Workaround of bugs in Openbox, Fluxbox, etc.
# no-fading-destroyed-argb = false


#################################
#   Transparency / Opacity      #
#################################


# Opacity of inactive windows. (0.1 - 1.0, defaults to 1.0)
# inactive-opacity = 1

# Opacity of window titlebars and borders. (0.1 - 1.0, disabled by default)
# frame-opacity = 1.0

# Let inactive opacity set by -i override the '_NET_WM_OPACITY' values of windows.
# inactive-opacity-override = true

# Default opacity for active windows. (0.0 - 1.0, defaults to 1.0)
# active-opacity = 1.0

# Dim inactive windows. (0.0 - 1.0, defaults to 0.0)
# inactive-dim = 0.0

# Specify a list of conditions of windows that should never be considered focused.
# focus-exclude = []
focus-exclude = [ "class_g = 'Cairo-clock'" ];

# Use fixed inactive dim value, instead of adjusting according to window opacity.
# inactive-dim-fixed = 1.0

# Specify a list of opacity rules, in the format `PERCENT:PATTERN`,
# like `50:name *= "Firefox"`. picom-trans is recommended over this.
# Note we don't make any guarantee about possible conflicts with other
# programs that set '_NET_WM_WINDOW_OPACITY' on frame or client windows.
# example:
#    opacity-rule = [ "80:class_g = 'URxvt'" ];
#
opacity-rule = [
    "90:name = 'alttab'",
    "80:name = 'i3-overview'",
    # no opacity on sticky windows
    "99:_NET_WM_STATE@:32a *= '_NET_WM_STATE_STICKY'"
];


#################################
#           Corners             #
#################################

# Sets the radius of rounded window corners. When > 0, the compositor will
# round the corners of windows. Does not interact well with
# `transparent-clipping`.
corner-radius = 0;

# Exclude conditions for rounded corners.
rounded-corners-exclude = [
  "window_type = 'dock'",
  "window_type = 'desktop'"
];


#################################
#     Background-Blurring       #
#################################


# Parameters for background blurring, see the *BLUR* section for more information.
# blur-method =
# blur-size = 12
#
# blur-deviation = false
#
# blur-strength = 5

# Blur background of semi-transparent / ARGB windows.
# Bad in performance, with driver-dependent behavior.
# The name of the switch may change without prior notifications.
#
# blur-background = false

# Blur background of windows when the window frame is not opaque.
# Implies:
#    blur-background
# Bad in performance, with driver-dependent behavior. The name may change.
#
# blur-background-frame = false

# Use fixed blur strength rather than adjusting according to window opacity.
# blur-background-fixed = false

# Specify the blur convolution kernel, with the following format:
# example:
#   blur-kern = "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
#
# blur-kern = ""
blur-kern = "3x3box";

# Exclude conditions for background blur.
# blur-background-exclude = []
blur-background-exclude = [
  "window_type = 'dock'",
  "window_type = 'desktop'",
  "_GTK_FRAME_EXTENTS@:c"
];


#################################
#       Colour-inversion        #
#################################

# Specify list of windows or x flag to that will be colour inverted.
invert-color-include = [
    "INVERT_FLAG@:8c"
];


#################################
#       General Settings        #
#################################

# Daemonize process. Fork to background after initialization. Causes issues with certain (badly-written) drivers.
# daemon = false

# Specify the backend to use: `xrender`, `glx`, or `xr_glx_hybrid`.
# `xrender` is the default one.
#
backend = "glx";

# Enable/disable VSync.
# vsync = false
vsync = true;

# Enable remote control via D-Bus. See the *D-BUS API* section below for more details.
# dbus = false

# Try to detect WM windows (a non-override-redirect window with no
# child that has 'WM_STATE') and mark them as active.
#
# mark-wmwin-focused = false
mark-wmwin-focused = true;

# Mark override-redirect windows that doesn't have a child window with 'WM_STATE' focused.
# mark-ovredir-focused = false
mark-ovredir-focused = true;

# Try to detect windows with rounded corners and don't consider them
# shaped windows. The accuracy is not very high, unfortunately.
#
# detect-rounded-corners = false

# Detect '_NET_WM_OPACITY' on client windows, useful for window managers
# not passing '_NET_WM_OPACITY' of client windows to frame windows.
#
# detect-client-opacity = false
detect-client-opacity = true;

# Specify refresh rate of the screen. If not specified or 0, picom will
# try detecting this with X RandR extension.
#
# refresh-rate = 60
refresh-rate = 0;

# Use EWMH '_NET_ACTIVE_WINDOW' to determine currently focused window,
# rather than listening to 'FocusIn'/'FocusOut' event. Might have more accuracy,
# provided that the WM supports it.
#
# use-ewmh-active-win = false
use-ewmh-active-win = true;

# Unredirect all windows if a full-screen opaque window is detected,
# to maximize performance for full-screen windows. Known to cause flickering
# when redirecting/unredirecting windows.
#
# unredir-if-possible = false

# Delay before unredirecting the window, in milliseconds. Defaults to 0.
# unredir-if-possible-delay = 0

# Conditions of windows that shouldn't be considered full-screen for unredirecting screen.
# unredir-if-possible-exclude = []

# Use 'WM_TRANSIENT_FOR' to group windows, and consider windows
# in the same group focused at the same time.
#
# detect-transient = false
detect-transient = true;

# Use 'WM_CLIENT_LEADER' to group windows, and consider windows in the same
# group focused at the same time. This usually means windows from the same application
# will be considered focused or unfocused at the same time.
# 'WM_TRANSIENT_FOR' has higher priority if detect-transient is enabled, too.
#
# detect-client-leader = false
detect-client-leader = true;

# Resize damaged region by a specific number of pixels.
# A positive value enlarges it while a negative one shrinks it.
# If the value is positive, those additional pixels will not be actually painted
# to screen, only used in blur calculation, and such. (Due to technical limitations,
# with use-damage, those pixels will still be incorrectly painted to screen.)
# Primarily used to fix the line corruption issues of blur,
# in which case you should use the blur radius value here
# (e.g. with a 3x3 kernel, you should use `--resize-damage 1`,
# with a 5x5 one you use `--resize-damage 2`, and so on).
# May or may not work with *--glx-no-stencil*. Shrinking doesn't function correctly.
#
# resize-damage = 1

# Specify a list of conditions of windows that should be painted with inverted color.
# Resource-hogging, and is not well tested.
#
# invert-color-include = []

# GLX backend: Avoid using stencil buffer, useful if you don't have a stencil buffer.
# Might cause incorrect opacity when rendering transparent content (but never
# practically happened) and may not work with blur-background.
# My tests show a 15% performance boost. Recommended.
#
# glx-no-stencil = false

# GLX backend: Avoid rebinding pixmap on window damage.
# Probably could improve performance on rapid window content changes,
# but is known to break things on some drivers (LLVMpipe, xf86-video-intel, etc.).
# Recommended if it works.
#
# glx-no-rebind-pixmap = false

# Disable the use of damage information.
# This cause the whole screen to be redrawn everytime, instead of the part of the screen
# has actually changed. Potentially degrades the performance, but might fix some artifacts.
# The opposing option is use-damage
#
# no-use-damage = false
use-damage = true;

# Use X Sync fence to sync clients' draw calls, to make sure all draw
# calls are finished before picom starts drawing. Needed on nvidia-drivers
# with GLX backend for some users.
#
# xrender-sync-fence = false
xrender-sync-fence = true;

# GLX backend: Use specified GLSL fragment shader for rendering window contents.
# See `compton-default-fshader-win.glsl` and `compton-fake-transparency-fshader-win.glsl`
# in the source tree for examples.
#
# glx-fshader-win = ""

# Force all windows to be painted with blending. Useful if you
# have a glx-fshader-win that could turn opaque pixels transparent.
#
# force-win-blend = false

# Do not use EWMH to detect fullscreen windows.
# Reverts to checking if a window is fullscreen based only on its size and coordinates.
#
# no-ewmh-fullscreen = false

# Dimming bright windows so their brightness doesn't exceed this set value.
# Brightness of a window is estimated by averaging all pixels in the window,
# so this could comes with a performance hit.
# Setting this to 1.0 disables this behaviour. Requires --use-damage to be disabled. (default: 1.0)
#
# max-brightness = 1.0

# Make transparent windows clip other windows like non-transparent windows do,
# instead of blending on top of them.
#
# transparent-clipping = false

# Set the log level. Possible values are:
#  "trace", "debug", "info", "warn", "error"
# in increasing level of importance. Case doesn't matter.
# If using the "TRACE" log level, it's better to log into a file
# using *--log-file*, since it can generate a huge stream of logs.
#
# log-level = "debug"
log-level = "warn";

# Set the log file.
# If *--log-file* is never specified, logs will be written to stderr.
# Otherwise, logs will to written to the given file, though some of the early
# logs might still be written to the stderr.
# When setting this option from the config file, it is recommended to use an absolute path.
#
# log-file = "/path/to/your/log/file"

# Show all X errors (for debugging)
# show-all-xerrors = false

# Write process ID to a file.
# write-pid-path = "/path/to/your/log/file"

# Window type settings
#
# 'WINDOW_TYPE' is one of the 15 window types defined in EWMH standard:
#     "unknown", "desktop", "dock", "toolbar", "menu", "utility",
#     "splash", "dialog", "normal", "dropdown_menu", "popup_menu",
#     "tooltip", "notification", "combo", and "dnd".
#
# Following per window-type options are available: ::
#
#   fade, shadow:::
#     Controls window-type-specific shadow and fade settings.
#
#   opacity:::
#     Controls default opacity of the window type.
#
#   focus:::
#     Controls whether the window of this type is to be always considered focused.
#     (By default, all window types except "normal" and "dialog" has this on.)
#
#   full-shadow:::
#     Controls whether shadow is drawn under the parts of the window that you
#     normally won't be able to see. Useful when the window has parts of it
#     transparent, and you want shadows in those areas.
#
#   clip-shadow-above:::
#     Controls wether shadows that would have been drawn above the window should
#     be clipped. Useful for dock windows that should have no shadow painted on top.
#
#   redir-ignore:::
#     Controls whether this type of windows should cause screen to become
#     redirected again after been unredirected. If you have unredir-if-possible
#     set, and doesn't want certain window to cause unnecessary screen redirection,
#     you can set this to `true`.
#
wintypes:
{
  tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; full-shadow = false; };
  dock = { shadow = false; clip-shadow-above = true; }
  dnd = { shadow = false; }
  #popup_menu = { opacity = 0.8; }
  #dropdown_menu = { opacity = 0.8; }
};

Enabling per window transparency with transset-df (and keybind changing it)

Using window transparencies effectively can make a big difference to the overall use and focus in managing lots of windows, especially when you might have a few sticky windows as well.

Although you can modify transparencies etc. by editing ~/.config/picom.conf, there's no functionality to increase or decrease transparencies 'on the fly' and for specific windows only.

You can achieve this with transset-df.  First you'll need to install it with

sudo pacman -S transset-df

Once installed, using transset-df is very straightforward, for example, to set transparency to 80%, simply call

transset-df 0.8

and then click on a window to set the transparency for that window.

We can do even better though with i3.  In my ~/.i3/config I've added

# window transparency adjustment (and alias to restart picom)
bindsym $mod+Mod1+z exec transset-df -a --min 0.25 --dec 0.25
bindsym $mod+Mod1+x exec transset-df -a --inc 0.25
bindsym $mod+Mod1+c exec --no-startup-id picom -b

These shortcuts will increase or decrease transparency of the currently selected window by +/-25%.  You might notice I also have a shortcut (mod+alt+c) for picom, which will reset start/reset picom.  You'll see why next.

I prefer my sticky windows to be opaque by default, and using the above I can then change them to suit. To change the default window transparency used for sticky windows you'll need to modify your picom config (~/.config/picom.conf) and make sure it contains 

"99:_NET_WM_STATE@:32a *= '_NET_WM_STATE_STICKY'"

in the opacity-rule array.

This works to my liking.  However, I've found that when I want to change my sticky window back to opaque, my default inactive-opacity setting for picom kicks in (in other words, when I select something else my sticky window is not quite opaque).  Resetting picom with mod+alt+c fixes this and reapplies my default transparency setting for sticky windows.

For reference here is my ~/.config/picom.conf

~/.config/picom.conf
#################################
#             Shadows           #
#################################


# Enabled client-side shadows on windows. Note desktop windows
# (windows with '_NET_WM_WINDOW_TYPE_DESKTOP') never get shadow,
# unless explicitly requested using the wintypes option.
#
# shadow = false

# The blur radius for shadows, in pixels. (defaults to 12)
# shadow-radius = 12

# The opacity of shadows. (0.0 - 1.0, defaults to 0.75)
# shadow-opacity = .75

# The left offset for shadows, in pixels. (defaults to -15)
# shadow-offset-x = -15

# The top offset for shadows, in pixels. (defaults to -15)
# shadow-offset-y = -15

# Red color value of shadow (0.0 - 1.0, defaults to 0).
# shadow-red = 0

# Green color value of shadow (0.0 - 1.0, defaults to 0).
# shadow-green = 0

# Blue color value of shadow (0.0 - 1.0, defaults to 0).
# shadow-blue = 0

# Hex string color value of shadow (#000000 - #FFFFFF, defaults to #000000). This option will override options set shadow-(red/green/blue)
# shadow-color = "#000000"

# Specify a list of conditions of windows that should have no shadow.
#
# examples:
#   shadow-exclude = "n:e:Notification";
#
# shadow-exclude = []
shadow-exclude = [
    "! name~=''",
    "name = 'Notification'",
    "name = 'Plank'",
    "name = 'Docky'",
    "name = 'Kupfer'",
    "name = 'xfce4-notifyd'",
    "name = 'cpt_frame_window'",
    "name *= 'VLC'",
    "name *= 'compton'",
    "name *= 'picom'",
    "name *= 'Chromium'",
    "name *= 'Chrome'",
    "class_g = 'Firefox' && argb",
    "class_g = 'Conky'",
    "class_g = 'Kupfer'",
    "class_g = 'Synapse'",
    "class_g ?= 'Notify-osd'",
    "class_g ?= 'Cairo-dock'",
    "class_g ?= 'Xfce4-notifyd'",
    "class_g ?= 'Xfce4-power-manager'",
    # disables shadows for hidden windows
    "_GTK_FRAME_EXTENTS@:c",
    "_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'",
    # disables shadows on sticky windows:
    "_NET_WM_STATE@:32a *= '_NET_WM_STATE_STICKY'",
    # disables shadows on i3 frames
    "class_g ?= 'i3-frame'",
    # workaround for conky until it provides window properties:
    "override_redirect = 1 && !WM_CLASS@:s"
];

# Specify a list of conditions of windows that should have no shadow painted over, such as a dock window.
# clip-shadow-above = []

# Specify a X geometry that describes the region in which shadow should not
# be painted in, such as a dock window region. Use
#    shadow-exclude-reg = "x10+0+0"
# for example, if the 10 pixels on the bottom of the screen should not have shadows painted on.
#
# shadow-exclude-reg = ""

# Crop shadow of a window fully on a particular Xinerama screen to the screen.
# xinerama-shadow-crop = false


#################################
#           Fading              #
#################################


# Fade windows in/out when opening/closing and when opacity changes,
#  unless no-fading-openclose is used.
# fading = false
fading = true;

# Opacity change between steps while fading in. (0.01 - 1.0, defaults to 0.028)
# fade-in-step = 0.028
fade-in-step = 0.03;

# Opacity change between steps while fading out. (0.01 - 1.0, defaults to 0.03)
# fade-out-step = 0.03
fade-out-step = 0.03;

# The time between steps in fade step, in milliseconds. (> 0, defaults to 10)
# fade-delta = 10
fade-delta = 4;

# Specify a list of conditions of windows that should not be faded.
# fade-exclude = []

# Do not fade on window open/close.
# no-fading-openclose = false

# Do not fade destroyed ARGB windows with WM frame. Workaround of bugs in Openbox, Fluxbox, etc.
# no-fading-destroyed-argb = false


#################################
#   Transparency / Opacity      #
#################################


# Opacity of inactive windows. (0.1 - 1.0, defaults to 1.0)
# inactive-opacity = 1

# Opacity of window titlebars and borders. (0.1 - 1.0, disabled by default)
# frame-opacity = 1.0

# Let inactive opacity set by -i override the '_NET_WM_OPACITY' values of windows.
# inactive-opacity-override = true

# Default opacity for active windows. (0.0 - 1.0, defaults to 1.0)
# active-opacity = 1.0

# Dim inactive windows. (0.0 - 1.0, defaults to 0.0)
# inactive-dim = 0.0

# Specify a list of conditions of windows that should never be considered focused.
# focus-exclude = []
focus-exclude = [ "class_g = 'Cairo-clock'" ];

# Use fixed inactive dim value, instead of adjusting according to window opacity.
# inactive-dim-fixed = 1.0

# Specify a list of opacity rules, in the format `PERCENT:PATTERN`,
# like `50:name *= "Firefox"`. picom-trans is recommended over this.
# Note we don't make any guarantee about possible conflicts with other
# programs that set '_NET_WM_WINDOW_OPACITY' on frame or client windows.
# example:
#    opacity-rule = [ "80:class_g = 'URxvt'" ];
#
opacity-rule = [
    "90:name = 'alttab'",
    "80:name = 'i3-overview'",
    # no opacity on sticky windows
    "99:_NET_WM_STATE@:32a *= '_NET_WM_STATE_STICKY'"
];


#################################
#           Corners             #
#################################

# Sets the radius of rounded window corners. When > 0, the compositor will
# round the corners of windows. Does not interact well with
# `transparent-clipping`.
corner-radius = 0;

# Exclude conditions for rounded corners.
rounded-corners-exclude = [
  "window_type = 'dock'",
  "window_type = 'desktop'"
];


#################################
#     Background-Blurring       #
#################################


# Parameters for background blurring, see the *BLUR* section for more information.
# blur-method =
# blur-size = 12
#
# blur-deviation = false
#
# blur-strength = 5

# Blur background of semi-transparent / ARGB windows.
# Bad in performance, with driver-dependent behavior.
# The name of the switch may change without prior notifications.
#
# blur-background = false

# Blur background of windows when the window frame is not opaque.
# Implies:
#    blur-background
# Bad in performance, with driver-dependent behavior. The name may change.
#
# blur-background-frame = false

# Use fixed blur strength rather than adjusting according to window opacity.
# blur-background-fixed = false

# Specify the blur convolution kernel, with the following format:
# example:
#   blur-kern = "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1";
#
# blur-kern = ""
blur-kern = "3x3box";

# Exclude conditions for background blur.
# blur-background-exclude = []
blur-background-exclude = [
  "window_type = 'dock'",
  "window_type = 'desktop'",
  "_GTK_FRAME_EXTENTS@:c"
];


#################################
#       Colour-inversion        #
#################################

# Specify list of windows or x flag to that will be colour inverted.
invert-color-include = [
    "INVERT_FLAG@:8c"
];


#################################
#       General Settings        #
#################################

# Daemonize process. Fork to background after initialization. Causes issues with certain (badly-written) drivers.
# daemon = false

# Specify the backend to use: `xrender`, `glx`, or `xr_glx_hybrid`.
# `xrender` is the default one.
#
backend = "glx";

# Enable/disable VSync.
# vsync = false
vsync = true;

# Enable remote control via D-Bus. See the *D-BUS API* section below for more details.
# dbus = false

# Try to detect WM windows (a non-override-redirect window with no
# child that has 'WM_STATE') and mark them as active.
#
# mark-wmwin-focused = false
mark-wmwin-focused = true;

# Mark override-redirect windows that doesn't have a child window with 'WM_STATE' focused.
# mark-ovredir-focused = false
mark-ovredir-focused = true;

# Try to detect windows with rounded corners and don't consider them
# shaped windows. The accuracy is not very high, unfortunately.
#
# detect-rounded-corners = false

# Detect '_NET_WM_OPACITY' on client windows, useful for window managers
# not passing '_NET_WM_OPACITY' of client windows to frame windows.
#
# detect-client-opacity = false
detect-client-opacity = true;

# Specify refresh rate of the screen. If not specified or 0, picom will
# try detecting this with X RandR extension.
#
# refresh-rate = 60
refresh-rate = 0;

# Use EWMH '_NET_ACTIVE_WINDOW' to determine currently focused window,
# rather than listening to 'FocusIn'/'FocusOut' event. Might have more accuracy,
# provided that the WM supports it.
#
# use-ewmh-active-win = false
use-ewmh-active-win = true;

# Unredirect all windows if a full-screen opaque window is detected,
# to maximize performance for full-screen windows. Known to cause flickering
# when redirecting/unredirecting windows.
#
# unredir-if-possible = false

# Delay before unredirecting the window, in milliseconds. Defaults to 0.
# unredir-if-possible-delay = 0

# Conditions of windows that shouldn't be considered full-screen for unredirecting screen.
# unredir-if-possible-exclude = []

# Use 'WM_TRANSIENT_FOR' to group windows, and consider windows
# in the same group focused at the same time.
#
# detect-transient = false
detect-transient = true;

# Use 'WM_CLIENT_LEADER' to group windows, and consider windows in the same
# group focused at the same time. This usually means windows from the same application
# will be considered focused or unfocused at the same time.
# 'WM_TRANSIENT_FOR' has higher priority if detect-transient is enabled, too.
#
# detect-client-leader = false
detect-client-leader = true;

# Resize damaged region by a specific number of pixels.
# A positive value enlarges it while a negative one shrinks it.
# If the value is positive, those additional pixels will not be actually painted
# to screen, only used in blur calculation, and such. (Due to technical limitations,
# with use-damage, those pixels will still be incorrectly painted to screen.)
# Primarily used to fix the line corruption issues of blur,
# in which case you should use the blur radius value here
# (e.g. with a 3x3 kernel, you should use `--resize-damage 1`,
# with a 5x5 one you use `--resize-damage 2`, and so on).
# May or may not work with *--glx-no-stencil*. Shrinking doesn't function correctly.
#
# resize-damage = 1

# Specify a list of conditions of windows that should be painted with inverted color.
# Resource-hogging, and is not well tested.
#
# invert-color-include = []

# GLX backend: Avoid using stencil buffer, useful if you don't have a stencil buffer.
# Might cause incorrect opacity when rendering transparent content (but never
# practically happened) and may not work with blur-background.
# My tests show a 15% performance boost. Recommended.
#
# glx-no-stencil = false

# GLX backend: Avoid rebinding pixmap on window damage.
# Probably could improve performance on rapid window content changes,
# but is known to break things on some drivers (LLVMpipe, xf86-video-intel, etc.).
# Recommended if it works.
#
# glx-no-rebind-pixmap = false

# Disable the use of damage information.
# This cause the whole screen to be redrawn everytime, instead of the part of the screen
# has actually changed. Potentially degrades the performance, but might fix some artifacts.
# The opposing option is use-damage
#
# no-use-damage = false
use-damage = true;

# Use X Sync fence to sync clients' draw calls, to make sure all draw
# calls are finished before picom starts drawing. Needed on nvidia-drivers
# with GLX backend for some users.
#
# xrender-sync-fence = false
xrender-sync-fence = true;

# GLX backend: Use specified GLSL fragment shader for rendering window contents.
# See `compton-default-fshader-win.glsl` and `compton-fake-transparency-fshader-win.glsl`
# in the source tree for examples.
#
# glx-fshader-win = ""

# Force all windows to be painted with blending. Useful if you
# have a glx-fshader-win that could turn opaque pixels transparent.
#
# force-win-blend = false

# Do not use EWMH to detect fullscreen windows.
# Reverts to checking if a window is fullscreen based only on its size and coordinates.
#
# no-ewmh-fullscreen = false

# Dimming bright windows so their brightness doesn't exceed this set value.
# Brightness of a window is estimated by averaging all pixels in the window,
# so this could comes with a performance hit.
# Setting this to 1.0 disables this behaviour. Requires --use-damage to be disabled. (default: 1.0)
#
# max-brightness = 1.0

# Make transparent windows clip other windows like non-transparent windows do,
# instead of blending on top of them.
#
# transparent-clipping = false

# Set the log level. Possible values are:
#  "trace", "debug", "info", "warn", "error"
# in increasing level of importance. Case doesn't matter.
# If using the "TRACE" log level, it's better to log into a file
# using *--log-file*, since it can generate a huge stream of logs.
#
# log-level = "debug"
log-level = "warn";

# Set the log file.
# If *--log-file* is never specified, logs will be written to stderr.
# Otherwise, logs will to written to the given file, though some of the early
# logs might still be written to the stderr.
# When setting this option from the config file, it is recommended to use an absolute path.
#
# log-file = "/path/to/your/log/file"

# Show all X errors (for debugging)
# show-all-xerrors = false

# Write process ID to a file.
# write-pid-path = "/path/to/your/log/file"

# Window type settings
#
# 'WINDOW_TYPE' is one of the 15 window types defined in EWMH standard:
#     "unknown", "desktop", "dock", "toolbar", "menu", "utility",
#     "splash", "dialog", "normal", "dropdown_menu", "popup_menu",
#     "tooltip", "notification", "combo", and "dnd".
#
# Following per window-type options are available: ::
#
#   fade, shadow:::
#     Controls window-type-specific shadow and fade settings.
#
#   opacity:::
#     Controls default opacity of the window type.
#
#   focus:::
#     Controls whether the window of this type is to be always considered focused.
#     (By default, all window types except "normal" and "dialog" has this on.)
#
#   full-shadow:::
#     Controls whether shadow is drawn under the parts of the window that you
#     normally won't be able to see. Useful when the window has parts of it
#     transparent, and you want shadows in those areas.
#
#   clip-shadow-above:::
#     Controls wether shadows that would have been drawn above the window should
#     be clipped. Useful for dock windows that should have no shadow painted on top.
#
#   redir-ignore:::
#     Controls whether this type of windows should cause screen to become
#     redirected again after been unredirected. If you have unredir-if-possible
#     set, and doesn't want certain window to cause unnecessary screen redirection,
#     you can set this to `true`.
#
wintypes:
{
  tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; full-shadow = false; };
  dock = { shadow = false; clip-shadow-above = true; }
  dnd = { shadow = false; }
  #popup_menu = { opacity = 0.8; }
  #dropdown_menu = { opacity = 0.8; }
};


Window Management and various other implementations in i3

My usage and window management approaches in i3 have evolved over time - and continue to evolve.  If you look through my dev branch you'll see many changes and things tried (and reverted) as I've slowly tried out things until I've found what works best for me.  That's one the many things I love about i3 (and linux in general).

Below are just a few of the window management approaches that have stuck with me.  Please note that these approaches might not work for you - and that's fine.  Feel free to adapt (or disregard) them.

Master-stack (stack-stack) swap stack window with master keybind

I find myself now generally using a "master-stack" approach to window management with i3.  More specifically, I have two "stacking" layouts (horizontally) side-by-side, like so:

That is, I have a "master" stacking layout on the left and use a "stack" stacking (or splitv) layout on the right.

Now, i3 is a manual tiling manager which means that to move windows you can move window manually from the "stack" layout to the master - however it won't automatically move the current "master" to the "stack" layout when doing so (other dynamic tiling managers usually do this in a master-stack layout).

We can however, simulate this basic concept with a bindsym which will move the focused "stack" window to the right (the "master" layout), focus up (to select the currently selected "master" window), move it right, and then focus on the (now new) master window.  Add the following to your i3.conf file (I've found $mod+m works well for me):

# master-stack keybinding (moves stack window to master and current master back to stack window)
bindsym $mod+m exec "i3-msg \\"move left; focus up; move right; focus left\\""

Quick demo of using the above bindsym to switch windows in master-stack layout:

My "special" window combiner bindsyms

Note I no longer use these.  I use of i3 is constantly evolving and I find myself using more of a "master-stack" or a "stack-stack" approach to window management.  As such, I haven't used the below approach much lately so have deprecated them (removed them) in my config.  These might work well for you though so give them a try!

I found that much of my time was spend combining two adjacent windows into a single container.  That is, say I have four application windows all in a tabbed container, like so:

Now, most of the time I just want to combine two windows (in this example, my browser window and the Atom window to the right) into a split h container.  To do this, you would usually do something like

  1. create split h container;
  2. focus on the right app window;
  3. move right app window left (which combines into container);
  4. focus back on left app.

The above steps result in:

Now, that gets rather tedious after doing it a thousand times. 

Thankfully, you can basically do all these steps and bind it to a single shortcut defined in you i3 config file.  Behold:

# special combo for horizontal split of two windows next to each other
bindsym $mod+x split h, layout splith, focus right, move left, focus left, $con_title
bindsym $mod+Shift+x split h, layout splith, focus left, move right, focus right, $con_title

The two bindsyms will combine in a split container with the right adjacent window ($mod+x) or with the adjacent window on the left ($mod+Shift+x).

I also have similar bindsyms for combining adjacent windows into a tabbed container:

# special combo for container tabbed split of two windows next to each other
bindsym $mod+z split h, layout tabbed, focus right, move left, focus left, $con_title
bindsym $mod+Shift+z split h, layout tabbed, focus left, move right, focus right, $con_title

Container renaming

Dynamic container renaming

I've noticed that when you have a heavy window workload (lots of windows) and you've containerised lots of them - container names kind of... suck.  That is, they almost become so convoluted that it's easy to get lost.  For example look at the screenshot below of a normal workload for me (during development):

Notice the container names at the top (stuff like T[filezilla putty H[chromium chromium]]...) I struggle to segregate and identify (remember) where I put that chromium or terminal window that I was working on.

Now notice the difference with the same workload but container names changed:

Can you see the difference?  I've simply renamed the containers into something I understand; I have a container to my git related stuff (git clients and stuff), a container for several IDEs I use, another for apps I'm using to deploy applications to several web servers, and a container with stuff related to the latest javascript question/problem I'm figuring out.  These are all much more recognisable to me and helps me avoid "too many obscure window titles" hell.

I recently found this post on reddit that outlined a few ways to rename containers on the fly.  This can be achieved with a single bindsym that uses zenity (so make sure you have the zenity package installed) to pop up an input window for you to enter a container name and then focuses on the window parent, renames the container and then focuses back on the child window.  Below I've embedded a modified version of the script into a single bindsym command:

# dynamic renaming of parent container
bindsym $mod+slash exec "answer=$(zenity --title=\\"i3-msg title_format\\" --text \\"Change %TITLE for parent container\\" --entry); if [ -n \\"$answer\\" ]; then i3-msg focus parent, title_format \\"<span foreground='pink'><b> $answer</b></span>\\", focus child; else i3-msg focus parent, title_format \\"<span foreground='pink'><b> %title</b></span>\\", focus child; fi"

I've bound it to $mod+slash ("/" key).

Automatic container renaming from selected window

The above method can be used to default any container name to that of (for example) the currently selected window at the time of creating the container.  By defining the following config variable:

set $con_title exec "answer=$(xdotool getwindowfocus getwindowname); i3-msg focus parent, title_format \\"<span foreground='#ff8c85'><b> ⮡$answer</b></span>\\", focus child"

 and appending to our special window combiner bindsyms (see sections above), like this:

# special combo for horizontal split of two windows next to each other
bindsym $mod+x split h, layout splith, focus right, move left, focus left, $con_title
bindsym $mod+Shift+x split h, layout splith, focus left, move right, focus right, $con_title

Will cause the container title (created by $mod+x etc.) to be based on the window title of the application selected at the time of container generation.

Changing title behaviour to default for a single container

I've created a simple bindsym shortcut ($mod+Mod1+slash) to change the container title of a single (selected) container back to i3 default (e.g. T[chromium]).

Reverting to previous window title behaviour altogether

If you don't like this container title behaviour simply change the $con_title definition to:

set $con_title focus parent; title_format "<span foreground='#ff8c85'><b> %title</b></span>"; focus child; title_format " %title"

Scratchpad specific applications and bind their showing/hiding to a key shortcut

The below is a deprecated approach to showing/hiding applications on the scratchpad.  I've moved to using more i3 native approaches

The i3 scratchpad is great holding area for application windows that you might want to keep hide from all workspaces until you need them.  I often use the scratchpad for applications like my email client (which I don't want to see until an email arrives etc.) or for an on-demand terminal (not really a drop-down terminal but similar use case), or for an application that I regularly want to (quickly) popup, retrieve information and then have it get out of the way just as quickly (like a password manager for example).

In order for the use case(s) above, you really want to bind the scratchpad application to a keyboard shortcut that can be pressed to show the scratchpad application, and then pressed again to hide said application.

I wrote several scripts and integrated these directly in my i3.conf.  They basically check if an application is running, if it's not then start it (where you can then scratchpad it with the normal shortcut: mod+Shift+minus).  If it is running (and already on the scratchpad) pressing the shortcut will show/hide said application.  Of course, you can write a script to do all this and call it from your i3.conf, but I prefer to explicitly define the bash script in my conf (partly to cut down on others needing to take copy of my scripts separately from my i3.conf file).

Enough waffling, some i3.conf examples:

Terminator (terminal application)

I use the very cool (I think) terminator.  See my i3.conf bindsym below:

bindsym $mod+Shift+Return exec "APP=\\"terminator\\"; CLASS=\\"Terminator\\"; if pgrep -x \\"$APP\\" > /dev/null 2>&1; then i3-msg \\"[class=\\"$CLASS\\"] scratchpad show\\"; else \\"$APP\\"; fi"

You'll note that I define separate bash variables ($APP, $CLASS) here as the command to start Terminator is "terminator" but the WM_CLASS (window class) returned is "Terminator".

KeeWeb

My bindsym for KeeWeb (keepass cross-platform client):

bindsym $mod+o exec "APP=\\"KeeWeb\\"; if pgrep -x \\"$APP\\" > /dev/null 2>&1; then i3-msg \\"[class=\\"$APP\\"] scratchpad show\\"; else \\"$APP\\"; fi"

Save i3 layouts with i3-layout-manager

This is now removed from my current config.  Was great but I no longer use it (plus was a bit experimental and had a few issues I ran into).  Would still recommend though if you like the idea of predefining i3 layouts.

i3 natively supports saving and loading specific window layouts with the i3-save-tree, however the implementation is not really "user ready" in the sense that you can't use it as is to easily save and load different layouts.

Tomáš Báča wrote a neat script that makes this functionality much simpler to use.

I find having set/defined layouts really eases managing complex window setups.  Often I am working with many windows in some complicated setup (with child window containers of window containers etc.) and want to just get back to something simple(r) - which can be surprisingly tedious 

I've also added three layouts (which can be loaded) I use most and have provided bindsyms for each in my i3 config file.  These are:

Layout fileLayout NameKeyboard shortcutDescription
layout-ALL-TABBED.jsonALL-TABBEDmod+Shift+wBasic layout with single (root) tab container.  Useful for when you have a complex window layout and want to remove all windows and place in simple tabbed layout.
layout-SPLIT-TWO-TABBED.jsonSPLIT-TWO-TABBEDmod+Shift+aLayout with two root child containers (horizontally split) with each root child container set to be a tabbed container.
layout-SPLIT-FOUR-TABBED.jsonSPLIT-FOUR-TABBEDmod+Shift+sLayout with four root child containers (screen partitioned into four quarters) with each root child container set to be a tabbed container.

You'll need to have the i3-layout-manager script in your system path for the i3.conf  shortcuts to work and load on startup.

You can clone the git repo (or even just download the script) and copy (or create a symbolic link) in your system path (I'd suggest /usr/local/bin), like below

git clone https://github.com/klaxalk/i3-layout-manager.git
cd i3-layout-manager
sudo cp layout_manager.sh /usr/local/bin/i3-layout-manager
sudo chmod +x /usr/local/bin/i3-layout-manager

Download (somewhere) and copy my layouts above into the ~/.layouts folder, e.g.:

cp layout-ALL-TABBED.json layout-SPLIT-TWO-TABBED.json layout-SPLIT-FOUR-TABBED.json ~/.layouts

References

  1. https://forum.manjaro.org/t/reversed-scrolling-in-i3-edition/25811
  2. https://wiki.archlinux.org/index.php/Libinput
  3. https://wiki.archlinux.org/index.php/Touchpad_Synaptics
  4. https://wiki.archlinux.org/index.php/Razer_Blade#2018_version
  5. https://forum.manjaro.org/t/how-disable-bios-beep-like-sound-in-some-applications/17094/5
  6. https://wiki.archlinux.org/index.php/GNOME/Keyring#PAM_method
  7. https://i3wm.org/i3status/manpage.html#_disk
  8. http://duncanlock.net/blog/2013/06/07/how-to-switch-to-compton-for-beautiful-tear-free-compositing-in-xfce/
  9. http://vadim-kirilchuk-linux.blogspot.com.au/2013/05/swap-file-for-hibernation.html
  10. https://github.com/DaveDavenport/rofi
  11. https://wiki.archlinux.org/index.php/Per-application_transparency
  12. https://forum.manjaro.org/t/manjaro-i3-how-to-use-lightdm-as-lockscreen/42131
  13. https://www.reddit.com/r/i3wm/comments/7f84ae/is_there_a_way_to_rename_parent_containers/
  14. https://github.com/klaxalk/i3-layout-manager