1. Prerequisites

This configuration assumes that the following packages are installed:

  • Essentials:
    • sway, obviously.
    • swayidle, provides power management.
    • swaylock, provides screen locking.
    • foot, my terminal emulator of choice.
    • systemd, for lower-level functionalities, though not a hard requirement.
  • Utilities:
    • wlsunset, wonderful day/night gamma adjustment tool.
    • light, to control backlight.
    • wireplumber, to manage audio devices.
    • playerctl, to control media players.
    • mako, notification daemon.
    • fuzzel, scriptable application launcher.
  • Typeface:
    • ttf-inconsolata

2. Related configurations

3. File structure

This configuration is currently laid out as follows:

├── config
├── rules
└── colorschemes/
    ├── nord
    ├── solarized
    └── zenburn

4. Variable definitions

Variables make my life easier and they can be referenced across different files, too. The following variable definitions are used all throughout this configuration to preserve a level of consistency that could not be achieved otherwise.

4.1. Keys

Define the modifiers and directional keys:

set {
    $Super  Mod4
    $Alt    Mod1
    $Left   h
    $Down   j
    $Up     k
    $Right  l

4.2. Workspaces

Moving between workspaces is the most common operation one does in a window manager so their key placement should be very convenient. Qtile happens to utilize a layout that is particularly easy to remember, by default it uses "qsdfuiop" as the default workspace names, each character being the name of an individual workspace and the key to reach it. I have borrowed this intuitive pattern and have been using it ever since, no matter the window manager.

set {
    $ws1  1:q
    $ws2  2:s
    $ws3  3:d
    $ws4  4:f

4.3. Modes

set {
    $session_mode "(L)ock ⋅ (S)leep ⋅ (R)eload ⋅ (Q)uit"
    $screenshot_mode "(A)rea ⋅ (O)utput ⋅ (W)indow"
    $citron_mode "(D)ate ⋅ (B)attery"
  • session_mode: Represents the mode used for managing the desktop session.
  • screenshot_mode: Represents the mode used for capturing screenshots.
  • screenshot_mode: Represents the mode used for getting the system status via notifications.

4.4. Miscellaneous

resize_factor represents the amount of pixels a particular window should expand/shrink in size when resizing it.

set $resize_factor 40px

5. Inputs

For more information on this topic, see sway-input(5).

5.1. Keyboard

It is possible to remap many keys and fool around with different keyboard layouts and formats using xkb_options, for more information, see xkeyboard-config(1).

input "type:keyboard" {
    xkb_layout    fr
    xkb_options   compose:prsc
    repeat_rate   50
    repeat_delay  250

It's very helpful, especially in text editors, to have a very short repeat_delay and a very high repeat_rate.

5.2. Touchpad

Nothing fancy is going on here, just natural scrolling as if one is paging through a book and adaptive acceleration because why would you have it any other way.

input "type:touchpad" {
    tap             enabled
    natural_scroll  enabled
    accel_profile   "adaptive"
    pointer_accel   0.3

5.3. Mouse

Move and resize windows with the mouse by holding the $Super key and the Left and Right mouse buttons respectively.

floating_modifier $Super normal

6. Keybindings

While this section uses bindsym to bind keys to commands, it does also use bindgesture to bind actions to touchpad gestures.

6.1. Highlighting windows

bindsym {
  $Super+$Left   focus Left
  $Super+$Down   focus down
  $Super+$Up     focus up
  $Super+$Right  focus right

6.2. Tiling windows

bindsym {
  $Super+Shift+$Left   move Left
  $Super+Shift+$Down   move down
  $Super+Shift+$Up     move up
  $Super+Shift+$Right  move right

bindgesture {
  swipe:3:up           move up
  swipe:3:down         move down
  swipe:3:left         move Left
  swipe:3:right        move right

6.3. Resizing windows

bindsym {
  $Super+Control+$Left   resize shrink width $resize_factor
  $Super+Control+$Down   resize shrink height $resize_factor
  $Super+Control+$Up     resize grow height $resize_factor
  $Super+Control+$Right  resize grow width $resize_factor

6.4. Moving between workspaces

bindsym {
  $Super+q      workspace $ws1
  $Super+s      workspace $ws2
  $Super+d      workspace $ws3
  $Super+f      workspace $ws4
  $Super+tab    workspace back_and_forth

bindgesture {
  swipe:4:right workspace prev
  swipe:4:left  workspace next

6.5. Moving windows between workspaces

bindsym {
  $Super+Shift+q  move container to workspace $ws1; workspace $ws1
  $Super+Shift+s  move container to workspace $ws2; workspace $ws2
  $Super+Shift+d  move container to workspace $ws3; workspace $ws3
  $Super+Shift+f  move container to workspace $ws4; workspace $ws4

6.6. Splitting windows

bindsym {
  $Super+greater  splith
  $Super+less     splitv
  $Super+u        layout toggle all

6.7. Window actions

bindsym {
  $Super+w        kill
  $Super+n        fullscreen
  $Super+b        fullscreen disable; floating toggle
  $Super+o        scratchpad show
  $Super+Space    focus mode_toggle
  $Super+asciicircum    sticky toggle
  $Super+Shift+o  move scratchpad

6.8. Playback control

bindsym {
  XF86AudioPlay  exec playerctl play-pause
  XF86AudioNext  exec playerctl next
  XF86AudioPrev  exec playerctl previous

6.9. Volume control

bindsym {
  XF86AudioRaiseVolume  exec wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 0.05+
  XF86AudioLowerVolume  exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.05-
  XF86AudioMute         exec wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle

6.10. Brightness control

bindsym {
  XF86MonBrightnessUp    exec light -A 5
  XF86MonBrightnessDown  exec light -U 5

6.11. Modes

Modes allow us to define keychords, which combine different actions into the same context and are much more ergonomic. The keybindings in this section are merely activators for the listed modes.

bindsym $Super+exclam    mode $session_mode
bindsym $Super+asterisk  mode $screenshot_mode
bindsym $Super+i         mode $citron_mode

6.12. Miscellaneous

bindsym {
  $Super+Return        exec footclient
  $Super+Shift+Return  exec swaymsg '[app_id=foot-dropdown]' focus || footclient --app-id=foot-dropdown
  $Super+Shift+e       exec emacsclient -c
  $Super+e             exec swaymsg '[app_id=emacs]' focus ||  emacsclient -c
  $Super+p             exec passmenu
  $Super+r             exec fuzzel --log-level error --lines 6 --prompt "⌘ "
  $Super+y             exec qutebrowser-sessions

7. Modes

7.1. Session

Upon entering this mode, I can choose to execute one of many session-related actions as listed below. I can also cancel at any time by hitting ESC.

mode $session_mode bindsym {
  r       reload, mode "default"
  l       exec loginctl lock-session, mode "default"
  s       exec systemctl suspend, mode "default"
  q       exec systemctl stop --user sway, mode "default"
  escape  mode "default"

7.2. Screenshot

Upon entering this mode, I have the choice of selecting the kind of screenshot I would like to take, which will then be placed in a standard directory for me to grab.

mode $screenshot_mode bindsym {
  a       exec grimshot save area, mode "default"
  o       exec grimshot save area, mode "default"
  w       exec grimshot save window, mode "default"
  escape  mode "default"

7.3. Citron

This mode allows me to display various details relating to the status of my computer (for example, network, battery and uptime statistics) in the form of a notification.

mode $citron_mode bindsym {
  b       exec citron battery, mode "default"
  d       exec citron date, mode "default"
  escape  mode "default"

8. Options

The status bar is configured to display only if the Super modifier is held, its primary role is to guide me as I navigate between workspaces which makes Super the most convenient and sensible modifier to use.

The philosophy here is that the status bar is less of an information center and more of a navigational guide.

bar {
    mode hide
    position bottom
    strip_workspace_numbers yes
    font Inconsolata 12
    swaybar_command true
    colors {
       statusline #ffffff
       background #32323200
       inactive_workspace #323232 #323232 #5C5C5C
       binding_mode #323232 #323232 #ffffff

Configure the default font to match that of the bar:

font Inconsolata 12

Declutter the desktop by hiding the cursor after a set period of inactivity:

seat * hide_cursor 10000

Disable Xwayland rather than having it lie dormant:

xwayland disable

Remove any thickness applied to the window borders:

titlebar_border_thickness 0

9. Colorschemes

This section defines a set of colorschemes which modify the many client properties exposed by sway.

Colorschemes are contained in separate files. Only one may be used at a time as they conflict with each other. To start using one, e.g. solarized, include the colorschemes/solarized file.

9.1. Default

This snippet will configure the properties of the status bar; it should be placed inside the bar directive.

statusline #ffffff
background #32323200
inactive_workspace #323232 #323232 #5C5C5C
binding_mode #323232 #323232 #ffffff

9.2. Solarized

Define the palette:

set {
    $base03   #002B36
    $base02   #073642
    $base01   #586E75
    $base00   #657B83
    $base0    #839496
    $base1    #93A1A1
    $base2    #EEE8D5
    $base3    #FDF6E3
    $yellow   #B58900
    $orange   #CB4B16
    $red      #DC322F
    $magenta  #D33682
    $violet   #6C71C4
    $blue     #268BD2
    $cyan     #2AA198
    $green    #859900

Set the different client properties:

client.focused            $base02  $base00  $base02  $green
client.focused_inactive   $base02  $base03  $base0
client.unfocused          $base02  $base03  $base0
client.urgent             $yellow  $yellow  $base03

9.3. Nord

Define the palette:

set {
    $base06   #2E3440
    $base05   #3B4252
    $base04   #434C5E
    $base03   #4C566A
    $base02   #D8DEE9
    $base01   #E5E9F0
    $base00   #ECEFF4
    $blue     #5E81AC
    $yellow   #EBCB8B
    $orange   #D08770
    $red      #BF616A
    $magenta  #B48EAD
    $green    #A3BE8C

Set the different client properties:

client.focused           $base03  $base03  $base00  $orange
client.focused_inactive  $base04  $base04  $base00
client.unfocused         $base06  $base06  $base00
client.urgent            $red     $red     $red

This snippet defines the properties of the status bar; it should be placed inside the bar.colors directive.

statusline          $base00
separator           $base03
background          $base06
focused_workspace   $blue $blue $base06
inactive_workspace  $base06 $base06 $base00 

9.4. Zenburn

Define the palette:

set {
    $base00   #292929
    $base01   #DCDCCC
    $base02   #3F3F3F
    $base03   #DCDCCC
    $base04   #AB6C71
    $base05   #709080

Set the different client properties:

client.focused            $base01  $base01  $base02  $base02
client.focused_inactive   $base02  $base02  $base03
client.unfocused          $base02  $base02  $base03
client.urgent             $base04  $base04  $base01

10. Imports

Import the rules file which defines all the window rules:

include rules

11. Window rules

Window rules allow me to customize the properties of windows programmatically, such properties include:

  • The location of said windows:
    • (X,Y) coordinates and/or the workspace to which they belong
  • Their geometry and decorations
  • Their effect on the compositor:
    • Inhibiting sleep
  • And so much more
for_window [app_id="pinentry-qt"] floating enable
for_window [app_id="lxqt-policykit-agent"] floating enable
for_window [app_id="pavucontrol"] floating enable
for_window [app_id="org.twosheds.iwgtk|iwgtk"] floating enable
for_window  [app_id="foot"] inhibit_idle fullscreen

Qutebrowser should inhibit idle (meaning the system will not go to sleep) when the window is fullscreen.

for_window [app_id="qutebrowser"] {
   inhibit_idle fullscreen

It's nice to be able to pop open a terminal right where you are, kind of like those dedicated dropdown terminal emulators.

for_window [app_id="^foot-dropdown$"] {
   move scratchpad
   scratchpad show
   floating enable
   sticky enable
   border none
   resize set height 500px
   resize set width 1920px
   move position 0 0
   opacity 0.9

There comes a time when a GUI file manager is really useful.

for_window [app_id="pcmanfm-qt"] {
   floating enable
   sticky enable

12. Integration

Given that the compositor is managed by systemd and that a number of other services, like wlsunset, swaybg, etc., require certain environment variables (for example, WAYLAND_DISPLAY) to be set in order to function properly, the compositor must therefore expose these two variables (without hardcoding them) and notify the service manager when it's ready, the latter will respond to this by starting the other services all the while respecting their sequencing (specified using the After or Before directive under the Unit section of .service files).

exec systemctl --user import-environment WAYLAND_DISPLAY SWAYSOCK
exec systemd-notify --ready