dotfiles/Desktop.org
2021-04-16 16:48:18 +03:00

54 KiB

Desktop

My general desktop environment configuration.

Parts prefixed with (OFF) are not used, but kept for historic purposes. For some reason GitHub's org renderer ignores TODO status, hence such a prefix. Round brackets instead of square ones to prevent GitHub's org renderer from screwing up.

Most of the colors are from the Palenight theme. Colorcodes are taken from this repo:

Color Default Lighter
Black #292d3e #434758
Red #f07178 #ff8b92
Green #c3e88d #ddffa7
Yellow #ffcb6b #ffe585
Blue #82aaff #9cc4ff
Magenta #c792ea #e1acff
Cyan #89ddff #a3f7ff
White #d0d0d0 #ffffff

i3wm

i3wm is a manual tiling window manager, which is currently my window manager of choice. I've tried several alternatives, including xmonad & EXWM, but i3 seems to fit my workflow best.

i3-gaps is an i3 fork with a few features like window gaps. I like to enable inner gaps when there is at least one container in a workspace.

References:

General settings

set $mod Mod4
font pango:monospace 10

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

# Move cursor between monitors
mouse_warping output

# Apply XFCE Settings
exec xfsettingsd
exec xiccd

# Most needed keybindigs
# reload the configuration file
bindsym $mod+Shift+c reload

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

# exit i3 (logs you out of your X session)
bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'"

Managing windows

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

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

# alternatively, you can use the cursor keys:
bindsym $mod+Left focus left
bindsym $mod+Down focus down
bindsym $mod+Up focus up
bindsym $mod+Right focus right

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

# alternatively, you can use the cursor keys:
bindsym $mod+Shift+Left move left
bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right

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

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

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

# change container layout (stacked, tabbed, toggle split)
bindsym $mod+w layout stacking
bindsym $mod+t layout tabbed
bindsym $mod+e layout toggle split

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

bindsym $mod+Tab move workspace to output right
bindsym $mod+q focus output right

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

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

# focus the child container
bindsym $mod+Shift+A focus child

Workspaces

set $w1 "1 🚀"
set $w2 "2 🌍"
set $w3 "3 💬"
set $w4 "4 🛠️️"
set $w7 "7 🛰️"
set $w8 "8 📝"
set $w9 "9 🎵"
set $w10 "10 📦"

bindsym $mod+1 workspace $w1
bindsym $mod+2 workspace $w2
bindsym $mod+3 workspace $w3
bindsym $mod+4 workspace $w4
bindsym $mod+5 workspace 5
bindsym $mod+6 workspace 6
bindsym $mod+7 workspace $w7
bindsym $mod+8 workspace $w8
bindsym $mod+9 workspace $w9
bindsym $mod+0 workspace $w10

# move focused container to workspace
bindsym $mod+Shift+1 move container to workspace $w1
bindsym $mod+Shift+2 move container to workspace $w2
bindsym $mod+Shift+3 move container to workspace $w3
bindsym $mod+Shift+4 move container to workspace $w4
bindsym $mod+Shift+5 move container to workspace 5
bindsym $mod+Shift+6 move container to workspace 6
bindsym $mod+Shift+7 move container to workspace $w7
bindsym $mod+Shift+8 move container to workspace $w8
bindsym $mod+Shift+9 move container to workspace $w9
bindsym $mod+Shift+0 move container to workspace $w10

# Cycle workspaces
bindsym $mod+comma workspace prev
bindsym $mod+period workspace next

Rules

Rules to automatically assign applications to workspaces and do other stuff, like enable floating.

Most apps can be distinguished by a WM class (you can get one with xprop), but in some cases it doesn't work, e.g. for terminal applications. In that case rules can be based on a window title, for instance.

However, watch out for the following: rule such as for_window [title="ncmpcpp.*"] move to workspace $w9 will move any windows with a title, starting with ncmpcpp to workspace $w9, which, for instance, may move your browser there if you google "ncmpcpp".

assign [class="Emacs"] $w1
assign [class="qutebrowser"] $w2
assign [class="firefox"] $w2
assign [class="VK"] $w3
assign [class="Slack"] $w3
assign [class="discord"] $w3
assign [class="TelegramDesktop"] $w3
assign [class="Postman"] $w4
assign [class="Chromium-browse"] $w4
assign [class="chromium"] $w4
assign [class="google-chrome"] $w4
assign [title="Vue Developer Tools"] $w4
assign [class="Google Play Music Desktop Player"] $w9
assign [class="jetbrains-datagrip"] $w4
assign [class="zoom"] $w7
assign [class="skype"] $w7
assign [class="Mailspring"] $w8
assign [class="Thunderbird"] $w8
assign [class="Joplin"] $w8
assign [class="keepassxc"] $w10

for_window [title="VirtScreen"] floating enable

for_window [title="ncmpcpp.*"] move to workspace $w9
for_window [title="newsboat.*"] move to workspace $w9
for_window [title=".*run_wego"] move to workspace $w9
for_window [class="cinnamon-settings*"] floating enable
for_window [title="Picture-in-Picture"] sticky enable

Scratchpad

Scratch terminal, inspired by this Luke Smith's video.

Launch script

First of all, we have to distinguish a scratchpad terminal from a normal one. To do that, one can create st with a required classname.

Then, it would be cool not to duplicate scratchpads, so the following script first looks for a window with a created classname. If it exists, the script just toggles the scratchpad visibility. Otherwise, a new instance of a window is created.

CLASSNAME="dropdown_tmux"
COMMAND="alacritty --class $CLASSNAME -e tmux new-session -s $CLASSNAME"
pid=$(xdotool search --classname "dropdown_tmux")
if [[ ! -z $pid  ]]; then
    i3-msg scratchpad show
else
    setsid -f ${COMMAND}
fi

i3 config

# Scratchpad
for_window [instance="dropdown_*"] floating enable
for_window [instance="dropdown_*"] move scratchpad
for_window [instance="dropdown_*"] sticky enable
for_window [instance="dropdown_*"] scratchpad show
for_window [instance="dropdown_*"] move position center

bindsym $mod+u exec ~/bin/scripts/dropdown

Gaps & borders

The main reason to use i3-gaps

# Borders
# for_window [class=".*"] border pixel 0
default_border pixel 3
hide_edge_borders both

# Gaps
set $default_inner 10
set $default_outer 0

gaps inner $default_inner
gaps outer $default_outer

smart_gaps on

Keybindings

mode "inner gaps" {
    bindsym plus gaps inner current plus 5
    bindsym minus gaps inner current minus 5
    bindsym Shift+plus gaps inner all plus 5
    bindsym Shift+minus gaps inner all minus 5
    bindsym 0 gaps inner current set 0
    bindsym Shift+0 gaps inner all set 0

    bindsym r gaps inner current set $default_inner
    bindsym Shift+r gaps inner all set $default_inner

    bindsym Return mode "default"
    bindsym Escape mode "default"
}

mode "outer gaps" {
    bindsym plus gaps outer current plus 5
    bindsym minus gaps outer current minus 5
    bindsym Shift+plus gaps outer all plus 5
    bindsym Shift+minus gaps outer all minus 5
    bindsym 0 gaps outer current set 0
    bindsym Shift+0 gaps outer all set 0

    bindsym r gaps outer current set $default_outer
    bindsym Shift+r gaps outer all set $default_outer

    bindsym Return mode "default"
    bindsym Escape mode "default"
}

bindsym $mod+g mode "inner gaps"
bindsym $mod+Shift+g mode "outer gaps"

Move & resize windows

A more or less standard set of keybindings to move & resize floating windows.

Just be careful to always make a way to return from these new modes, otherwise, you'd end up in a rather precarious position.

# resize window (you can also use the mouse for that)
mode "resize" {
    # These bindings trigger as soon as you enter the resize mode

    bindsym h resize shrink width 10 px or 10 ppt
    bindsym j resize grow height 10 px or 10 ppt
    bindsym k resize shrink height 10 px or 10 ppt
    bindsym l resize grow width 10 px or 10 ppt

    bindsym Shift+h resize shrink width 100 px or 100 ppt
    bindsym Shift+j resize grow height 100 px or 100 ppt
    bindsym Shift+k resize shrink height 100 px or 100 ppt
    bindsym Shift+l resize grow width 100 px or 100 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

    bindsym Shift+Left resize shrink width 100 px or 100 ppt
    bindsym Shift+Down resize grow height 100 px or 100 ppt
    bindsym Shift+Up resize shrink height 100 px or 100 ppt
    bindsym Shift+Right resize grow width 100 px or 100 ppt

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

bindsym $mod+r mode "resize"

mode "move" {
    bindsym $mod+Tab focus right

    bindsym Left  move left
    bindsym Down  move down
    bindsym Up    move up
    bindsym Right move right

    bindsym h     move left
    bindsym j     move down
    bindsym k     move up
    bindsym l     move right

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

bindsym $mod+m mode "move" focus floating

OFF (OFF) Intergration with dmenu

dmenu is a dynamic menu program for X. I've opted out of using it in favour of rofi, but here is a relevant bit of config.

Scripts are located in the bin/scripts folder.

# dmenu
bindsym $mod+d exec i3-dmenu-desktop --dmenu="dmenu -l 10"
bindsym $mod+apostrophe mode "dmenu"

mode "dmenu" {
    bindsym d exec i3-dmenu-desktop --dmenu="dmenu -l 10"; mode default
    bindsym p exec dmenu_run -l 10; mode default
    bindsym m exec dmenu-man; mode default
    bindsym b exec dmenu-buku; mode default
    bindsym f exec dmenu-explore; mode default
    bindsym t exec dmenu-tmuxp; mode default
    bindsym Escape mode "default"
}

bindsym $mod+b exec --no-startup-id dmenu-buku

Integration with rofi

Keybindings to launch rofi. For more detail, look the /sqrtminusone/dotfiles/src/commit/6ebf968c017f93e3a8b4c33acd2cfd291f22963e/*Rofi section.

bindsym $mod+d exec "rofi -modi 'drun,run' -show drun"
bindsym $mod+b exec --no-startup-id rofi-buku-mine

bindsym $mod+apostrophe mode "rofi"

mode "rofi" {
    bindsym d exec "rofi -modi 'drun,run' -show drun"
    bindsym m exec rofi-man; mode default
    bindsym b exec rofi-buku-mine; mode default
    bindsym k exec rofi-keepassxc -d ~/MEGAsync/Passwords.kdbx; mode default
    bindsym Escape mode "default"
}

Launching apps & misc keybindings

I prefer to use a separate mode to launch most of my apps, with some exceptions.

Apps

# Launch apps
# start a terminal at workspace 1
bindsym $mod+Return exec "i3-msg 'workspace 1 🚀; exec alacritty'"

bindsym $mod+p exec "copyq menu"
bindsym $mod+Shift+x exec "i3lock -f -i /home/pavel/Pictures/lock-wallpaper.png"

bindsym $mod+semicolon mode "apps"

mode "apps" {
    bindsym Escape mode "default"
    bindsym b exec firefox; mode default
    bindsym v exec vk-messenger; mode default
    bindsym s exec slack; mode default;
    bindsym m exec "alacritty -e ncmpcpp"; mode default
    bindsym c exec "copyq toggle"; mode default
    bindsym k exec "keepassxc"; mode default
    # bindsym e exec mailspring; mode default
    bindsym a exec "bash /home/pavel/bin/emacs.sh"; mode default
    bindsym n exec "alacritty -e newsboat"; mode default
    bindsym w exec "alacritty /home/pavel/bin/scripts/run_wego"; mode default
    # bindsym a exec emacsclient -c; mode default
    # bindsym Shift+a exec emacs; mode default
}

Media controls & brightness

# Pulse Audio controls
bindsym XF86AudioRaiseVolume exec --no-startup-id "pactl set-sink-volume @DEFAULT_SINK@ +5%"
bindsym XF86AudioLowerVolume exec --no-startup-id "pactl set-sink-volume @DEFAULT_SINK@ -5%"
bindsym XF86AudioMute exec --no-startup-id "pactl set-sink-mute @DEFAULT_SINK@ toggle"

exec --no-startup-id xmodmap -e 'keycode 135 = Super_R' && xset -r 135
bindsym $mod+F2 exec --no-startup-id "pactl set-sink-volume @DEFAULT_SINK@ -5%"
bindsym $mod+F3 exec --no-startup-id "pactl set-sink-volume @DEFAULT_SINK@ +5%"

# Media player controls
bindsym XF86AudioPlay exec mpc toggle
bindsym XF86AudioPause exec mpc pause
bindsym XF86AudioNext exec mpc next
bindsym XF86AudioPrev exec mpc prev

# Screen brightness
bindsym XF86MonBrightnessUp exec xbacklight -inc 5
bindsym XF86MonBrightnessDown exec xbacklight -dec 5

Screenshots

# Screenshots
bindsym --release Print exec "flameshot gui"
bindsym --release Shift+Print exec "xfce4-screenshooter"

Colors

Application of the palenight theme to the WM.

# Colors
set $bg-color 	         #292d3e
set $active-color        #82aaff
set $inactive-bg-color   #434758
set $text-color          #f3f4f5
set $inactive-text-color #aaaaaa
set $urgent-bg-color     #f07178
set $urgent-text-color   #000000

# window colors
#                       border              background         text                 indicator       child border
client.focused          $active-color       $bg-color          $text-color          $bg-color       $active-color
client.unfocused        $bg-color           $inactive-bg-color $inactive-text-color $bg-color       $bg-color
client.focused_inactive $active-color  $inactive-bg-color $inactive-text-color $bg-color       $bg-color
client.urgent           $urgent-bg-color    $urgent-bg-color   $urgent-text-color   $bg-color       $urgent-bg-color

OFF (OFF) i3blocks

I've opted out of i3bar & i3blocks for polybar

bar {
    status_command i3blocks -c ~/.config/i3/i3blocks.conf
    i3bar_command i3bar
    font pango:monospace 12
    output HDMI-A-0
    tray_output none
    colors {
        background $bg-color
        separator #757575
        #                  border             background         text
        focused_workspace  $bg-color          $bg-color          $text-color
        inactive_workspace $inactive-bg-color $inactive-bg-color $inactive-text-color
        urgent_workspace   $urgent-bg-color   $urgent-bg-color   $urgent-text-color
    }
}

bar {
    status_command i3blocks -c ~/.config/i3/i3blocks.conf
    i3bar_command i3bar
    font pango:monospace 10
    output DVI-D-0
    colors {
        background $bg-color
        separator #757575
        #                  border             background         text
        focused_workspace  $bg-color          $bg-color          $text-color
        inactive_workspace $inactive-bg-color $inactive-bg-color $inactive-text-color
        urgent_workspace   $urgent-bg-color   $urgent-bg-color   $urgent-text-color
    }
}

Keyboard Layout

A script to set Russian-English keyboard layout:

setxkbmap -layout us,ru
setxkbmap -model pc105 -option 'grp:win_space_toggle' -option 'grp:alt_shift_toggle'

A script to toggle the layout

if setxkbmap -query | grep -q us,ru; then
    setxkbmap -layout us
    setxkbmap -option
else
    setxkbmap -layout us,ru
    setxkbmap -model pc105 -option 'grp:win_space_toggle' -option 'grp:alt_shift_toggle'
fi

And the relevant i3 settings:

# Layout
exec_always --no-startup-id set_layout
bindsym $mod+slash exec toggle_layout

Autostart

# Polybar
exec_always --no-startup-id "bash /home/pavel/bin/polybar.sh"

# PulseEffects
exec --no-startup-id pulseeffects --gapplication-service

# Sudo
exec --no-startup-id /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1

# Wallpaper
exec_always "feh --bg-fill ~/Pictures/wallpaper-2.jpg"

# Picom
exec picom

# Keynav
exec keynav

# Applets
exec --no-startup-id /usr/bin/nm-applet
exec --no-startup-id /usr/bin/blueman-applet

# MPD
exec --no-startup-id mpd

# Stuff
exec aw-qt
exec "vnstatd -d"
exec dunst
exec kde-connect-indicator
exec copyq
exec "xmodmap ~/.Xmodmap"
exec "bash ~/bin/autostart.sh"

Polybar

Polybar is a nice-looking, WM-agnostic statusbar program.

I switched to polybar because I wanted to try out some WMs other than i3, but decided to stick with i3 for now.

References:

Launching

The script below allows me to:

  • have different blocks on my two different-sized monitors and my laptop;
  • have different settings on my desktop PC and laptop;
hostname=$(hostname)
# Settings varying on the hostname
if [ "$hostname" = "pntk" ]; then
    TRAY_MONITOR="eDP1"
    export WLAN_INTERFACE="wlp3s0"
else
    TRAY_MONITOR="HDMI-A-0"
    export WLAN_INTERFACE="wlp35s0f3u2"
fi

# Setting varying on the monitor
declare -A FONT_SIZES=(
    ["eDP1"]="13"
    ["DVI-D-0"]="11"
    ["HDMI-A-0"]="13"
)
declare -A EMOJI_SCALE=(
    ["eDP1"]="9"
    ["DVI-D-0"]="10"
    ["HDMI-A-0"]="10"
)
declare -A BAR_HEIGHT=(
    ["eDP1"]="29"
    ["DVI-D-0"]="23"
    ["HDMI-A-0"]="29"
)
declare -A BLOCKS=(
    ["DVI-D-0"]="pulseaudio SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP weather SEP sun aw-afk date TSEP"
    ["HDMI-A-0"]="pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP weather SEP sun aw-afk date TSEP"
    ["eDP1"]="pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP battery SEP sun aw-afk date TSEP"
)

# Geolocation for some modules
export LOC="SPB"

pkill polybar
for m in $(xrandr --query | grep " connected" | cut -d" " -f1); do
    export MONITOR=$m
    if [ "$MONITOR" = "$TRAY_MONITOR" ]; then
        export TRAY="right"
    else
        export TRAY="none"
    fi
    SIZE=${FONT_SIZES[$MONITOR]}
    SCALE=${EMOJI_SCALE[$MONITOR]}
    if [[ -z "$SCALE" ]]; then
        continue
    fi
    export FONT0="pango:monospace:size=$SIZE;1"
    export FONT1="NotoEmoji:scale=$SCALE:antialias=false;1"
    export FONT2="fontawesome:pixelsize=$SIZE;1"
    export FONT3="JetBrains Mono Nerd Font:monospace:size=$SIZE;1"
    export HEIGHT=${BAR_HEIGHT[$MONITOR]}
    export RIGHT_BLOCKS=${BLOCKS[$MONITOR]}
    polybar mybar &
done

General settings

Colors

[colors]
; Palenight colorscheme https://github.com/JonathanSpeek/palenight-iterm2
black = #292d3e
red = #f07178
green = #c3e88d
yellow = #ffcb6b
blue = #82aaff
magenta = #c792ea
cyan = #89ddff
white = #d0d0d0

black-lighter = #434758
red-lighter = #ff8b92
green-lighter = #ddffa7
yellow-lighter = #ffe585
blue-lighter = #9cc4ff
magenta-lighter = #9cc4ff
cyan-lighter = #9cc4ff
white-lighter = ffffff

background = ${colors.black}
; background = #ee292d3e
foreground = ${colors.white}

Bar config

[bar/mybar]
monitor = ${env:MONITOR:}
width = 100%
height = ${env:HEIGHT:27}
offset-x = 0
offset-y = 0
radius = 0.0
fixed-center = false
bottom=true

background = ${colors.background}
foreground = ${colors.foreground}

line-size = 3
line-color = #f00

padding-left = 0
padding-right = 0

module-margin-left = 1
module-margin-right = 1

font-0 = ${env:FONT0:pango:monospace:size=10;1}
font-1 = ${env:FONT1:NotoEmoji:scale=10:antialias=false;0}
font-2 = ${env:FONT2:fontawesome:pixelsize=10;1}
font-3 = ${env:FONT3:JetBrains Mono Nerd Font:monospace:size=10;1}

modules-left = i3
; modules-center = test
modules-right = ${env:RIGHT_BLOCKS}

tray-position = ${env:TRAY:right}
tray-padding = 0
tray-maxsize = 16
;tray-background = #0063ff

wm-restack = i3
; override-redirect = true

scroll-up = i3wm-wsnext
scroll-down = i3wm-wsprev

; cursor-click = pointer
; cursor-scroll = ns-resize

[settings]
screenchange-reload = true
;compositing-background = xor
;compositing-background = screen
;compositing-foreground = source
;compositing-border = over
;pseudo-transparency = false

[global/wm]
margin-top = 0
margin-bottom = 0

Modules

ipstack-vpn

A module to get a country of the current IP and openvpn status. Uses ipstack API.

ip=$(dig +short +timeout=1 myip.opendns.com @resolver1.opendns.com 2> /dev/null)
API_KEY="$(cat ~/secrets/ipstack-api-key)"
if [[ -z $ip || $ip == *"timed out"* ]]; then
    echo "%{u#f07178}%{+u} ?? %{u-}"
    exit
fi
ip_info=$(curl -s http://api.ipstack.com/${ip}?access_key=${API_KEY})
# emoji=$(echo $ip_info | jq -r '.location.country_flag_emoji')
code=$(echo $ip_info | jq -r '.country_code')
vpn=$(pgrep -a openvpn$ | head -n 1 | awk '{print $NF }' | cut -d '.' -f 1)

if [ -n "$vpn" ]; then
    echo "%{u#9cc4ff}%{+u}  $code %{u-}"
else
    echo "%{u#f07178}%{+u}  $code %{u-}"
fi
[module/ipstack-vpn]
type = custom/script
exec = /home/pavel/bin/polybar/ipstack-vpn.sh
interval = 1200

weather

Gets current weather from wttr.in

bar_format="${BAR_FORMAT:-"%t"}"
location="${LOCATION:-"Saint-Petersburg"}"
format_1=${FORMAT_1:-"qF"}
format_2=${FORMAT_1:-"format=v2n"}

bar_weather=$(curl -s wttr.in/${location}?format=${bar_format} || echo "??")
if [ -z "$bar_weather" ]; then
    exit 1
elif [[ "$bar_weather" == *"Unknown"* || "$bar_weather" == *"Sorry"* || "$bar_weather" == *"Bad Gateway"* ]]; then
    echo "??"
    exit 1
else
    echo ${bar_weather}
fi
[module/weather]
type = custom/script
exec = /home/pavel/bin/polybar/weather.sh
format-underline = ${colors.red}
interval = 1200

aw-afk

Prints out a current uptime and non-AFK time from ActivityWatch server

Type Note
TODO Fix crash on uptime > 99h
afk_event=$(curl -s -X GET "http://localhost:5600/api/0/buckets/aw-watcher-afk_$(hostname)/events?limit=1" -H "accept: application/json")
status=$(echo ${afk_event} | jq -r '.[0].data.status')
afk_time=$(echo "${afk_event}" | jq -r '.[0].duration' | xargs -I !  date -u -d @! +"%H:%M")

uptime=$(datediff "$(uptime -s | xargs -I ! date -d ! -Iseconds)" "$(date -Iseconds)" -f '%H:%M' | xargs -I ! date -d ! +"%H:%M")
res="${afk_time} / ${uptime}"
if [[ $status == 'afk' ]]; then
    echo "%{u#f07178}%{+u} [AFK] $res %{u-}"
else
    echo "%{u#82aaff}%{+u} $res %{u-}"
fi
[module/aw-afk]
type = custom/script
exec = /home/pavel/bin/polybar/aw_afk.sh
interval = 60

sun

Prints out the time of sunrise/sunset. Uses sunwait

declare -A LAT_DATA=(
    ["TMN"]="57.15N"
    ["SPB"]="59.9375N"
)
declare -A LON_DATA=(
    ["TMN"]="65.533333E"
    ["SPB"]="30.308611E"
)
if [ -z "$LOC" ]; then
    echo "LOC?"
    exit -1
fi
LAT=${LAT_DATA[$LOC]}
LON=${LON_DATA[$LOC]}

time=$(sunwait poll daylight rise ${LAT} $LON)

if [[ ${time} == 'DAY' ]]; then
    sunset=$(sunwait list daylight set ${LAT} ${LON})
    echo "%{u#ffcb6b}%{+u} $sunset %{u-}"
else
    sunrise=$(sunwait list daylight rise ${LAT} ${LON})
    echo "%{u#f07178}%{+u} $sunrise %{u-}"
fi
[module/sun]
type = custom/script
exec = /home/pavel/bin/polybar/sun.sh
interval = 60

SEP

A simple separator

[module/SEP]
type = custom/text
content = "|"
content-foreground = ${colors.magenta}
content-padding = 0
content-margin = 0
interval = 0

TSEP

A separator, which appears only if monitor is set to have a tray in the launch script

if [ ! -z "$TRAY" ] && [ "$TRAY" != "none" ]; then
    echo "| "
fi
[module/TSEP]
type = custom/script
exec = /home/pavel/bin/polybar/tray-sep.sh
format-foreground = ${colors.magenta}
interval = 0

i3

Show i3wm workspaces

[module/i3]
type = internal/i3
format = <label-state> <label-mode>
index-sort = true
wrapping-scroll = false

; Only show workspaces on the same output as the bar
pin-workspaces = true

label-mode-padding = 1
label-mode-foreground = #000
label-mode-background = ${colors.blue}

; focused = Active workspace on focused monitor
label-focused = %name%
; label-focused-background = ${colors.background-alt}
label-focused-underline= ${colors.blue}
label-focused-padding = 1

; unfocused = Inactive workspace on any monitor
label-unfocused = %name%
label-unfocused-padding = 1

; visible = Active workspace on unfocused monitor
label-visible = %name%
; label-visible-background = ${self.label-focused-background}
label-visible-underline = ${self.label-focused-underline}
label-visible-padding = ${self.label-focused-padding}

; urgent = Workspace with urgency hint set
label-urgent = %name%
label-urgent-background = ${colors.red}
label-urgent-foreground = ${colors.black}
label-urgent-padding = 1

xkeyboard

Current keyboard layout

[module/xkeyboard]
type = internal/xkeyboard
format = <label-layout>

format-underline = ${colors.magenta}
label-layout = %icon%
layout-icon-0 = ru;RU
layout-icon-1 = us;US

mpd

Music Player Daemon status

[module/mpd]
type = internal/mpd

format-playing = <toggle> <label-time> <label-song>
format-paused = <toggle> <label-time> <label-song>
format-stopped = 
label-song = [%album-artist%] %title%
label-time = %elapsed%/%total%

label-song-maxlen = 30
label-song-ellipsis = true

format-playing-underline = ${colors.yellow}
format-paused-underline = ${colors.yellow}
format-stopped-underline = ${colors.yellow}

label-separator = 0
separator-foreground = ${colors.red}

icon-pause = 
icon-play = 
icon-stop = 
icon-prev = 1
icon-next = 2

pulseaudio

PulseAudio status

[module/pulseaudio]
type = internal/pulseaudio
use-ui-max = true

bar-volume-width = 7
bar-volume-foreground-0 = ${colors.white}
bar-volume-foreground-1 = ${colors.yellow}
bar-volume-foreground-2 = ${colors.yellow}
bar-volume-foreground-3 = ${colors.blue}
bar-volume-foreground-4 = ${colors.blue}
bar-volume-foreground-5 = ${colors.green}
bar-volume-foreground-6 = ${colors.green}
bar-volume-gradient = false
bar-volume-indicator = |
bar-volume-indicator-font = 2
bar-volume-fill = ─
bar-volume-fill-font = 2
bar-volume-empty = ─
bar-volume-empty-font = 2
bar-volume-empty-foreground = ${colors.white-lighter}

format-volume = ♪ <bar-volume> <label-volume>
label-volume = %percentage%%

format-mute = ♪ <label-muted>
label-muted = MUTE

format-volume-underline = ${colors.white}
format-muted-underline = ${colors.black-lighter}

cpu

CPU usage

[module/cpu]
type = internal/cpu
format =   <label>
label = %percentage%%
format-underline = ${colors.green-lighter}

ram-memory

RAM usage

[module/ram-memory]
type = internal/memory
interval = 10

ramp-used-0 = ▁
ramp-used-1 = ▂
ramp-used-2 = ▃
ramp-used-3 = ▄
ramp-used-4 = ▅
ramp-used-5 = ▆
ramp-used-6 = ▇
ramp-used-7 = █

format =  <label>
label=%gb_used:.1f%

format-underline = ${colors.blue}

swap-memory

Swap usage

[module/swap-memory]
type = internal/memory
interval = 10

label= %gb_swap_used:.1f%
format-underline = ${colors.yellow}

network

Upload/download speed

[module/network]
type = internal/network
interval = 1

interface = ${env:WLAN_INTERFACE}

; format-connected = [<ramp-signal>] <label-connected>

label-connected = ↓ %downspeed% ↑ %upspeed%
label-disconnected = X

format-connected-underline = ${colors.green}
format-disconnected-underline = ${colors.red}

ramp-signal-0 = 0
ramp-signal-1 = 1
ramp-signal-2 = 2
ramp-signal-3 = 3
ramp-signal-4 = 4	
ramp-signal-5 = 5

date

Current date

[module/date]
type = internal/date
interval = 5

date =
date-alt = "%Y-%m-%d"

time = %H:%M
time-alt = %H:%M:%S

format-underline = ${colors.cyan}
label = "%date% %time%"

battery

[module/battery]
type = internal/battery
battery = BAT0
adapter = ADP0

time-format = %H:%M
format-discharging = <ramp-capacity> <label-discharging>
format-discharging-underline = ${colors.cyan}
format-charging-underline = ${colors.yellow}
format-full-underline = ${colors.green}
label-discharging = %percentage%% %time%
label-charging =  %percentage%% %time%

ramp-capacity-0 = 
ramp-capacity-1 = 
ramp-capacity-2 = 
ramp-capacity-3 = 
ramp-capacity-4 = 

Rofi

rofi is another dynamic menu generator. It can act as dmenu replacement but offers a superset of dmenu's features.

Theme

A theme is based on dracula theme for rofi. Probably no reason to keep it in this file.

/* Generated from [[file:../../Desktop.org::*Theme][Theme:1]] */
 * {
    black: #292d3e;
    red: #f07178;
    green: #c3e88d;
    yellow: #ffcb6b;
    blue: #82aaff;
    magenta: #82aaff;
    cyan: #89ddff;
    white: #d0d0d0;
    black-alternate: #393F57;
    black-lighter: #434758;
    red-lighter: #ff8b92;
    green-lighter: #ddffa7;
    yellow-lighter: #ffe585;
    blue-lighter: #9cc4ff;
    magenta-lighter: #e1acff;
    cyan-lighter: #a3f7ff;
    white-lighter: #ffffff;

    foreground:                  @white;
    background:                  @black;
    background-color:            @black;
    separatorcolor:              @magenta;
    border-color:                @magenta;
    selected-normal-foreground:  @black;
    selected-normal-background:  @magenta;
    selected-active-foreground:  @black;
    selected-active-background:  @blue;
    selected-urgent-foreground:  @foreground;
    selected-urgent-background:  @red;
    normal-foreground:           @foreground;
    normal-background:           @background;
    active-foreground:           @blue;
    active-background:           @background;
    urgent-foreground:           @red;
    urgent-background:           @background;
    alternate-normal-foreground: @foreground;
    alternate-normal-background: @black-alternate;
    alternate-active-foreground: @blue;
    alternate-active-background: @black-alternate;
    alternate-urgent-foreground: @red;
    alternate-urgent-background: @black-alternate;
    spacing:                     2;
}
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 dash 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-color:     @normal-foreground;
    handle-width:     8px ;
    padding:          0;
}
sidebar {
    border:           2px dash 0px 0px ;
    border-color:     @separatorcolor;
}
button {
    spacing:          0;
    text-color:       @normal-foreground;
}
button selected {
    background-color: @selected-normal-background;
    text-color:       @selected-normal-foreground;
}
inputbar {
    spacing:          0px;
    text-color:       @normal-foreground;
    padding:          1px ;
    children:         [ prompt,textbox-prompt-colon,entry,case-indicator ];
}
case-indicator {
    spacing:          0;
    text-color:       @normal-foreground;
}
entry {
    spacing:          0;
    text-color:       @normal-foreground;
}
prompt {
    spacing:          0;
    text-color:       @normal-foreground;
}
textbox-prompt-colon {
    expand:           false;
    str:              ":";
    margin:           0px 0.3000em 0.0000em 0.0000em ;
    text-color:       inherit;
}

Scripts

Buku bookmarks

Inspired by the knatsakis/rofi-buku script.

if [ $(hostname) = 'pdsk' ]; then
    BUKU="/home/pavel/.local/bin/buku"
else
    BUKU="/home/pavel/Programs/miniconda3/bin/buku"
fi

# COMMAND="$BUKU -o %"
# COMMAND="qutebrowser $(buku -f 10 -p %)"
COMMAND="firefox %"
if [[ $1 == '-e' ]]; then
    COMMAND="$BUKU -w %"
fi
$BUKU -f 4 -p | awk -F'\t' -v OFS='\t' '{
    split($4, tags, ",")
    joined = sep = ""
    for (i = 1; i in tags; i++) {
        joined = joined sep "[" tags[i] "]"
        sep = " "
    }
    url = substr($2, 1, 40)
    if (length($2) > 40) {
        url = url "..."
    }
    if ($1 != "waiting for input") {
        printf "%-5s %-60s %-45s %s\n", $1, $3, url, joined
    }
}' | sort -k 2 | rofi -dmenu -matching normal -sort -sorting-method fzf -width 80 -l 20 | cut -d ' ' -f 1 | {
    read index;
    if [[ -z "$index" ]]; then
        exit 0
    fi
    url=$($BUKU -f 10 -p $index)
    echo ${url#"waiting for input"} | cut -d ' ' -f 1 | xargs -I % $COMMAND
}

Man pages

Inspired by this Luke Smith's video.

A script to open a man page with zathura. There is no particular reason why one should look through man pages in pdf viewer rather than in console, but why not.

SELECTED=$(man -k . | rofi -dmenu -l 20 | awk '{print $1}')
if [[ ! -z $SELECTED ]]; then
    man -Tpdf $SELECTED | zathura -
fi

Flameshot

flameshot is my program of choice to make screenshots.

As it overwrites its own config all the time, I do not keep the file in VC.

[General]
disabledTrayIcon=false
drawColor=#ff0000
drawThickness=0
saveAfterCopyPath=/home/pavel/Pictures
savePath=/home/pavel/Pictures
savePathFixed=false
showStartupLaunchMessage=false
uiColor=#82aaff

[Shortcuts]
TYPE_ARROW=A
TYPE_CIRCLE=C
TYPE_CIRCLECOUNT=
TYPE_COMMIT_CURRENT_TOOL=Ctrl+Return
TYPE_COPY=Ctrl+C
TYPE_DRAWER=D
TYPE_EXIT=Ctrl+Q
TYPE_IMAGEUPLOADER=Return
TYPE_MARKER=M
TYPE_MOVESELECTION=Ctrl+M
TYPE_MOVE_DOWN=Down
TYPE_MOVE_LEFT=Left
TYPE_MOVE_RIGHT=Right
TYPE_MOVE_UP=Up
TYPE_OPEN_APP=Ctrl+O
TYPE_PENCIL=P
TYPE_PIN=
TYPE_PIXELATE=B
TYPE_RECTANGLE=R
TYPE_REDO=Ctrl+Shift+Z
TYPE_RESIZE_DOWN=Shift+Down
TYPE_RESIZE_LEFT=Shift+Left
TYPE_RESIZE_RIGHT=Shift+Right
TYPE_RESIZE_UP=Shift+Up
TYPE_SAVE=Ctrl+S
TYPE_SELECTION=S
TYPE_SELECTIONINDICATOR=
TYPE_SELECT_ALL=Ctrl+A
TYPE_TEXT=T
TYPE_TOGGLE_PANEL=Space
TYPE_UNDO=Ctrl+Z

dunst

Type Note
TODO Cleanup default config comments

dunst is a lightweight notification daemon.

My customizations of the original config consist mostly of changing colors.

References:

[global]
    monitor = 0

    follow = mouse

    # 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 respectively.
    # 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 = "300x5-30+20"

    # Show how many messages are currently hidden (because of geometry).
    indicate_hidden = yes

    # Shrink window if it's smaller than the width.  Will be ignored if
    # width is 0.
    shrink = no

    # The transparency of the window.  Range: [0; 100].
    # This option will only work if a compositing window manager is
    # present (e.g. xcompmgr, compiz, etc.).
    transparency = 15

    # The height of the entire notification.  If the height is smaller
    # than the font height and padding combined, it will be raised
    # to the font height and padding.
    notification_height = 0

    # Draw a line of "separator_height" pixel height between two
    # notifications.
    # Set to 0 to disable.
    separator_height = 2

    # Padding between text and separator.
    padding = 8

    # Horizontal padding.
    horizontal_padding = 8

    # Defines width in pixels of frame around the notification window.
    # Set to 0 to disable.
    frame_width = 1

    # Defines color of the frame around the notification window.
    frame_color = "#aaaaaa"

    # 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 = frame

    # Sort messages by urgency.
    sort = yes

    # 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.
    # A client can set the 'transient' hint to bypass this. See the rules
    # section for how to disable this if necessary
    idle_threshold = 120

    ### Text ###

    font = DejaVu Sans 9

    # The spacing between lines.  If the height is smaller than the
    # font height, it will get raised to the font height.
    line_height = 0

    # Possible values are:
    # full: Allow a small subset of html markup in notifications:
    #        <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>.
    #
    # strip: This setting is provided for compatibility with some broken
    #        clients that send markup even though it's not enabled on the
    #        server. Dunst will try to strip the markup but the parsing is
    #        simplistic so using this option outside of matching rules for
    #        specific applications *IS GREATLY DISCOURAGED*.
    #
    # no:    Disable markup parsing, incoming notifications will be treated as
    #        plain text. Dunst will not advertise that it has the body-markup
    #        capability if this is set as a global setting.
    #
    # It's important to note that markup inside the format option will be parsed
    # regardless of what this is set to.
    markup = full

    # 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
    #   %n  progress value if set without any extra characters
    #   %%  Literal %
    # Markup is allowed
    format = "<b>%s</b>\n%b"

    # Alignment of message text.
    # Possible values are "left", "center" and "right".
    alignment = left

    # 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 = yes

    # When word_wrap is set to no, specify where to make an ellipsis in long lines.
    # Possible values are "start", "middle" and "end".
    ellipsize = middle

    # Ignore newlines '\n' in notifications.
    ignore_newline = no

    # Stack together notifications with the same content
    stack_duplicates = true

    # Hide the count of stacked notifications with the same content
    hide_duplicate_count = false

    # Display indicators for URLs (U) and actions (A).
    show_indicators = yes

    ### Icons ###

    # Align icons left/right/off
    icon_position = left

    # Scale larger icons down to this size, set to 0 to disable
    max_icon_size = 32

    # Paths to default icons.
    icon_path = /usr/share/icons/Mint-Y/status/32/;/usr/share/icons/Mint-Y/devices/32

    ### History ###

    # 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

    ### Misc/Advanced ###

    # dmenu path.
    dmenu = /usr/bin/dmenu -p dunst:

    # Browser for opening urls in context menu.
    browser = /usr/bin/sensible-browser

    # Always run rule-defined scripts, even if the notification is suppressed
    always_run_script = true

    # Define the title of the windows spawned by dunst
    title = Dunst

    # Define the class of the windows spawned by dunst
    class = Dunst

    # Print a notification on startup.
    # This is mainly for error detection, since dbus (re-)starts dunst
    # automatically after a crash.
    startup_notification = false

    # Manage dunst's desire for talking
    # Can be one of the following values:
    #  crit: Critical features. Dunst aborts
    #  warn: Only non-fatal warnings
    #  mesg: Important Messages
    #  info: all unimportant stuff
    # debug: all less than unimportant stuff
    verbosity = mesg

    # Define the corner radius of the notification window
    # in pixel size. If the radius is 0, you have no rounded
    # corners.
    # The radius will be automatically lowered if it exceeds half of the
    # notification height to avoid clipping text and/or icons.
    corner_radius = 0

    ### Legacy

    # Use the Xinerama extension instead of RandR for multi-monitor support.
    # This setting is provided for compatibility with older nVidia drivers that
    # do not support RandR and using it on systems that support RandR is highly
    # discouraged.
    #
    # By enabling this setting dunst will not be able to detect when a monitor
    # is connected or disconnected which might break follow mode if the screen
    # layout changes.
    force_xinerama = false

    ### mouse

    # Defines action of mouse event
    # Possible values are:
    # * none: Don't do anything.
    # * do_action: If the notification has exactly one action, or one is marked as default,
    #              invoke it. If there are multiple and no default, open the context menu.
    # * close_current: Close current notification.
    # * close_all: Close all notifications.
    mouse_left_click = close_current
    mouse_middle_click = do_action
    mouse_right_click = close_all

# Experimental features that may or may not work correctly. Do not expect them
# to have a consistent behaviour across releases.
[experimental]
    # Calculate the dpi to use on a per-monitor basis.
    # If this setting is enabled the Xft.dpi value will be ignored and instead
    # dunst will attempt to calculate an appropriate dpi value for each monitor
    # using the resolution and physical size. This might be useful in setups
    # where there are multiple screens with very different dpi values.
    per_monitor_dpi = false

[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 = ctrl+space

    # Close all notifications.
    close_all = ctrl+shift+space

    # Redisplay last message(s).
    # On the US keyboard layout "grave" is normally above TAB and left
    # of "1". Make sure this key actually exists on your keyboard layout,
    # e.g. check output of 'xmodmap -pke'
    history = ctrl+grave

    # Context menu.
    context = ctrl+shift+period

[urgency_low]
    # IMPORTANT: colors have to be defined in quotation marks.
    # Otherwise the "#" and following would be interpreted as a comment.
    background = "#434758"
    frame_color = "#ffffff"
    foreground = "#d0d0d0"
    timeout = 10
    # Icon for notifications with low urgency, uncomment to enable
    #icon = /path/to/icon

[urgency_normal]
    background = "#292d3e"
    foreground = "#d0d0d0"
    frame_color = "#ffffff"
    timeout = 10
    # Icon for notifications with normal urgency, uncomment to enable
    #icon = /path/to/icon

[urgency_critical]
    background = "#f07178"
    foreground = "#ffffff"
    frame_color = "#f07178"
    timeout = 0
    # Icon for notifications with critical urgency, uncomment to enable
    #icon = /path/to/icon

keynav

Type Note
SYMLINK ./config/keynavrc -> .keynavrc

How many times you have been working with keyboard-driven programs and had to use a mouse just to press some pesky little button in a modal window?

keynav is a program that allows you to control the mouse with the keyboard with the general idea of bisecting the screen to get to the required point. I'm still not sure if there is any point in using it, but it's rather funny. Unfortunately, the colors seem to be hardcoded.

One of the usecases I found so far is to use the program to scroll webpages when tridactyl's scroll captures the wrong scroll area.

References:

Config

# clear all previous keybindings
clear

# Start & stop
ctrl+semicolon start
Super_L+bracketright start
Super_R+bracketright start
Escape end
ctrl+bracketleft end

# Macros
q record ~/.keynav_macros
shift+at playback

# Bisecting
a history-back
Left cut-left
Right cut-right
Down cut-down
Up cut-up
h cut-left
j cut-down
k cut-up
l cut-right
t windowzoom                          # Zoom to the current window
c cursorzoom 300 300                  # Limit the bisection area by 300x300

# Move the bisecting area
shift+h move-left
shift+j move-down
shift+k move-up
shift+l move-right
shift+Left move-left
shift+Right move-right
shift+Up move-up
shift+Down move-down

# Actions
space warp,click 3,end                # Right click
Return warp,click 1,end               # Left click
Shift+Return warp,doubleclick 1,end   # Double left click
semicolon warp,end                    # Move the cursor and exit
w warp                                # Just move the cursor
e end                                 # exit
u warp,click 4                        # scroll up
d warp,click 5                        # scroll down
1 click 1
2 click 2
3 click 3
4 click 4
5 click 5

Using with picom

I've noticed that the program does not play nice with picom's fade effect. To fix that, add the following to you config:

fade-exclude = [
  "class_i = 'keynav'",
  "class_g = 'keynav'",
]

Picom

picom is a compositor for X11. It allows effects such as transparency, blurring, etc.

Sample configuration is a good resource for getting an overview of the available settings. I have only a bunch of necessary settings in mine.

There are a bunch of forks for picom (e.g. ibhagwan/picom adds rounded corners) which seem to have some popularity, but I use the base one.

References:

Shadows

shadow = true;
shadow-radius = 2;
shadow-offset-x = -2;
shadow-offset-y = -2;

shadow-exclude = [
  "name = 'Notification'",
  "class_g = 'Conky'",
  "name ?= 'cpt_frame_window'",
  "class_g ?= 'Notify-osd'",
  "class_g = 'Cairo-clock'",
  "_GTK_FRAME_EXTENTS@:c"
];

Fading

fading = true

fade-in-step = 0.03;
fade-out-step = 0.03;
fade-delta = 10

fade-exclude = [
  "class_i = 'keynav'",
  "class_g = 'keynav'",
]

Opacity

I don't use stuff like transparency for inactive windows.

The first 5 lines of opacity-rule make i3wm's hidden windows 100% transparent, so I see the background behind the semi-transparent windows in i3wm's stacked and tabbed layout. Here is StackExchange question about that.

I also noticed that for some reason it doesn't play well with Emacs's built-in transparency, so the last line sets up Emacs transparency at 90%.

inactive-opacity = 1;

frame-opacity = 1.0;
inactive-opacity-override = false;
focus-exclude = [ "class_g = 'Cairo-clock'" ];

opacity-rule = [
  "0:_NET_WM_STATE@[0]:32a = '_NET_WM_STATE_HIDDEN'",
  "0:_NET_WM_STATE@[1]:32a = '_NET_WM_STATE_HIDDEN'",
  "0:_NET_WM_STATE@[2]:32a = '_NET_WM_STATE_HIDDEN'",
  "0:_NET_WM_STATE@[3]:32a = '_NET_WM_STATE_HIDDEN'",
  "0:_NET_WM_STATE@[4]:32a = '_NET_WM_STATE_HIDDEN'",
  "90:class_g = 'Emacs'"
];

General settings

Default general settings. Editing some of these may be neeeded in case of performance issues.

backend = "xrender";
vsync = true
mark-wmwin-focused = true;
mark-ovredir-focused = true;
detect-rounded-corners = true;
detect-client-opacity = true;
refresh-rate = 0
detect-transient = true
detect-client-leader = true
use-damage = true
log-level = "warn";

wintypes:
{
  tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; full-shadow = false; };
  dock = { shadow = false; }
  dnd = { shadow = false; }
  popup_menu = { opacity = 1; }
  dropdown_menu = { opacity = 1; }
};