Last modified: 2023-04-08
sway
I used to use GNOME, and I was relatively happy with it. However there were problem. For example GNOME
does not used configuration files like normal program, rather uses dconf and I hate it. It is very difficult to version the configuration as other dotfiles.
And then with GNOME
version 40 came changes ... they changed keyboard shortcuts, they changed workspace layout, they changed preview ... just terrible. I hated these changes mostly because they were less efficient with screen space and also made no sense. So for a while I was using vertical-overview GNOME
extension to fix these problems.
As the extension maintainer put it:
Gnome has had vertically stacked workspaces for a long time. The Gnome 40 update unfortunately made the switch to a horizontal layout. A choice that many Gnome users disagree with. This extension Aims to replace the new Gnome overview with something that resembles the old style.
But it was time to look for alternatives.
Friends of mine were using sway and it looked awesome! Not gonna lie, it took a while to get used to it, but the transition was worth it.
sway
is quite modular, checkout section useful add ons in their wiki.
Installation
As with most of my systems, I handle the installation via meta packages. Here is the specific one for sway
:
# Maintainer: Vojtech Vesely <vojtech.vesely@protonmail.com>
pkgname=wht_sway
pkgver=1.0.10
pkgrel=2
pkgdesc='archlinux meta package - sway desktop'
arch=('x86_64')
url='https://git.sr.ht/~atomicfs/atomicfs-repo-arch'
license=('MIT')
depends=(
# Other meta packages
'wht_system'
# System stuff
'networkmanager' # Network connection manager and user applications
'networkmanager-openvpn' # NetworkManager VPN plugin for OpenVPN
# Sway
'bemenu-wayland' # Wayland - wlroots-based compositors - renderer for bemenu
'foot' # Fast, lightweight, and minimalistic Wayland terminal emulator
'greetd' # Generic greeter daemon
'greetd-tuigreet' # A console UI greeter for greetd
'kanshi' # Dynamic output configuration for Wayland WMs
'mako' # Lightweight notification daemon for Wayland
'sway' # Tiling Wayland compositor and replacement for the i3 window manager
'swaybg' # Wallpaper tool for Wayland compositors
'swaylock' # Screen locker for Wayland
'wl-clipboard' # Command-line copy/paste utilities for Wayland
'wlsunset' # Day/night gamma adjustments for Wayland compositors
'xorg-xwayland' # run X clients under wayland
# Sway statusbars
'waybar' # Highly customizable Wayland bar for Sway and Wlroots based compositors
# Sway screenshots and screen sharing
'grim' # Screenshot utility for Wayland
'slurp' # Select a region in a Wayland compositor
'wf-recorder' # Screen recorder for wlroots-based compositors such as sway
# Fonts
'noto-fonts' # Google Noto TTF fonts
'otf-font-awesome' # Iconic font designed for Bootstrap
'ttf-font-awesome' # Iconic font designed for Bootstrap
# Audio
'pamixer' # Pulseaudio command-line mixer like amixer
'pavucontrol' # PulseAudio Volume Control
'pipewire' # Low-latency audio/video router and processor
'pipewire-pulse' # Low-latency audio/video router and processor - PulseAudio replacement
# Editors
'zathura' # Minimalistic document viewer
'zathura-cb'
'zathura-djvu'
'zathura-pdf-poppler'
'zathura-ps'
# Utilities
'exa' # ls replacement
)
Add your user into the seat
group. If the group does not exists, create it.
# gpasswd -a atom seat
Login manager
You do not need login manager, but I use it. Specifically tuigreet.
Edit the configuration file at /etc/greetd/config.toml
:
[terminal]
# The VT to run the greeter on. Can be "next", "current" or a number
# designating the VT.
vt = 1
# The default session, also known as the greeter.
[default_session]
# `agreety` is the bundled agetty/login-lookalike. You can replace `$SHELL`
# with whatever you want started, such as `sway`.
command = "tuigreet --cmd sway --time --time-format '%F %T'"
# The user to run the command as. The privileges this user must have depends
# on the greeter. A graphical greeter may for example require the user to be
# in the `video` group.
user = "greeter"
And then enable the greetd.service
and you are ready to go.
# systemctl enable greetd.service
Sway configuration
sway
is configured by ~/.config/sway/config
. It is usable from the start, but feel free to fool around ;)
Here is my main sway
configuration file, but things were moved into separate files into ~/.config/sway/config.d/
directory
~/.config/sway/config
# Read `man 5 sway` for a complete reference.
# bind keys to codes instead of symbols so the bindings work in all KB layouts
set $bindkey bindsym --to-code
font pango:Noto Sans Mono 10
input type:keyboard {
xkb_layout "us,cz"
xkb_variant ",qwerty"
xkb_options "grp:win_space_toggle"
xkb_numlock enable
}
# Gaps
gaps inner 8
smart_gaps on
### Variables
#
# Logo key. Use Mod1 for Alt.
set $mod Mod4
# Home row direction keys, like vim
set $left h
set $down j
set $up k
set $right l
# Your preferred terminal emulator
set $term foot
# Your preferred application launcher
# Note: pass the final command to swaymsg so that the resulting window can be opened
# on the original workspace that the command was run on.
#set $menu dmenu_path | dmenu | xargs swaymsg exec --
### Key bindings
#
# Basics:
#
# Start a terminal
$bindkey $mod+Return exec $term
# Kill focused window
$bindkey $mod+Shift+q kill
# Start your launcher
#$bindkey $mod+d exec $menu
$bindkey $mod+d exec bemenu-run --prompt ">"
# Drag floating windows by holding down $mod and left mouse button.
# Resize them with right mouse button + $mod.
# Despite the name, also works for non-floating windows.
# Change normal to inverse to use left mouse button for resizing and right
# mouse button for dragging.
floating_modifier $mod normal
# Reload the configuration file
$bindkey $mod+Shift+c reload
# Exit sway (logs you out of your Wayland session)
$bindkey $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -B 'Yes, exit sway' 'swaymsg exit'
#
# Moving around:
#
# Move your focus around
$bindkey $mod+$left focus left
$bindkey $mod+$down focus down
$bindkey $mod+$up focus up
$bindkey $mod+$right focus right
# Or use $mod+[up|down|left|right]
$bindkey $mod+Left focus left
$bindkey $mod+Down focus down
$bindkey $mod+Up focus up
$bindkey $mod+Right focus right
# Move the focused window with the same, but add Shift
$bindkey $mod+Shift+$left move left
$bindkey $mod+Shift+$down move down
$bindkey $mod+Shift+$up move up
$bindkey $mod+Shift+$right move right
# Ditto, with arrow keys
$bindkey $mod+Shift+Left move left
$bindkey $mod+Shift+Down move down
$bindkey $mod+Shift+Up move up
$bindkey $mod+Shift+Right move right
#
# Workspaces:
#
# Switch to workspace
$bindkey $mod+1 workspace number 1
$bindkey $mod+2 workspace number 2
$bindkey $mod+3 workspace number 3
$bindkey $mod+4 workspace number 4
$bindkey $mod+5 workspace number 5
$bindkey $mod+6 workspace number 6
$bindkey $mod+7 workspace number 7
$bindkey $mod+8 workspace number 8
$bindkey $mod+9 workspace number 9
$bindkey $mod+0 workspace number 10
# Move focused container to workspace
$bindkey $mod+Shift+1 move container to workspace number 1
$bindkey $mod+Shift+2 move container to workspace number 2
$bindkey $mod+Shift+3 move container to workspace number 3
$bindkey $mod+Shift+4 move container to workspace number 4
$bindkey $mod+Shift+5 move container to workspace number 5
$bindkey $mod+Shift+6 move container to workspace number 6
$bindkey $mod+Shift+7 move container to workspace number 7
$bindkey $mod+Shift+8 move container to workspace number 8
$bindkey $mod+Shift+9 move container to workspace number 9
$bindkey $mod+Shift+0 move container to workspace number 10
# Note: workspaces can have any name you want, not just numbers.
# We just use 1-10 as the default.
#
# Layout stuff:
#
# You can "split" the current object of your focus with
# $mod+b or $mod+v, for horizontal and vertical splits
# respectively.
$bindkey $mod+b splith
$bindkey $mod+v splitv
# Switch the current container between different layout styles
$bindkey $mod+s layout stacking
$bindkey $mod+w layout tabbed
$bindkey $mod+e layout toggle split
# Make the current focus fullscreen
$bindkey $mod+f fullscreen
# Toggle the current focus between tiling and floating mode
$bindkey $mod+Shift+space floating toggle
# Swap focus between the tiling area and the floating area
$bindkey $mod+space focus mode_toggle
# Move focus to the parent container
$bindkey $mod+a focus parent
#
# Scratchpad:
#
# Sway has a "scratchpad", which is a bag of holding for windows.
# You can send windows there and get them back later.
# Move the currently focused window to the scratchpad
$bindkey $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.
$bindkey $mod+minus scratchpad show
#
# Resizing containers:
#
mode "resize" {
# left will shrink the containers width
# right will grow the containers width
# up will shrink the containers height
# down will grow the containers height
$bindkey $left resize shrink width 10px
$bindkey $down resize grow height 10px
$bindkey $up resize shrink height 10px
$bindkey $right resize grow width 10px
# Ditto, with arrow keys
$bindkey Left resize shrink width 10px
$bindkey Down resize grow height 10px
$bindkey Up resize shrink height 10px
$bindkey Right resize grow width 10px
# Return to default mode
$bindkey Return mode "default"
$bindkey Escape mode "default"
}
$bindkey $mod+r mode "resize"
# Volume keys
$bindkey XF86AudioRaiseVolume exec pamixer -i 5
$bindkey XF86AudioLowerVolume exec pamixer -d 5
$bindkey XF86AudioMute exec pamixer -t
# Brightness keys
$bindkey XF86MonBrightnessDown exec brightnessctl set 10%-
$bindkey XF86MonBrightnessUp exec brightnessctl set +10%
$bindkey $mod+o exec $swaylock
# Toggle screenbacklight
$bindkey $mod+Pause exec ${HOME}/.config/sway/scripts/backlight_toggle.sh
# Screenshots
set $screenshot grim "/tmp/screenshot_$(date +'%Y-%m-%d_%H-%M-%S-%N').png"
set $screenshot_sel grim -g "$(slurp)" "/tmp/screenshot_$(date +'%Y-%m-%d_%H-%M-%S-%N').png"
$bindkey $mod+Print exec $screenshot && notify-send --expire-time=2000 "Full screenshot saved as /tmp/screenshot_$(date +'%Y-%m-%d_%H-%M-%S-%N').png !"
$bindkey $mod+Shift+Print exec $screenshot_sel && notify-send --expire-time=2000 "Selection screenshot saved as /tmp/screenshot_$(date +'%Y-%m-%d_%H-%M-%S-%N').png!"
include /etc/sway/config.d/*
include ${HOME}/.config/sway/config.d/*.conf
exec_always "systemctl --user import-environment; systemctl --user start sway-session.target"
- Terminal opens with
Super+Enter
sway
config reloads withSuper+Shift+c
.
Super
key is the key with logo (often Windows logo)
Waybar configuration
While the default status bar is perfectly fine, I have decided recently to switch to waybar. It is cool and allows you to do all kinds of crazy stuff.
config
/* WARNING: Do not edit this file.
* It was generated by processing {{ yadm.source }}
*/
/* DOCS:
* https://github.com/Alexays/Waybar/wiki
*/
{
"layer": "bottom",
"position": "top",
"height": 30,
"spacing": 6, // Gaps between modules in pixels
"modules-left": [
"sway/workspaces",
"sway/mode",
"sway/scratchpad",
"custom/media"
],
"modules-center": [],
"modules-right": [
{% if yadm.hostname == "saturn" %}
"temperature#gpu",
{% endif %}
"temperature",
"battery",
"battery#bat2",
"backlight",
"network",
"cpu",
"memory",
"disk",
"pulseaudio",
"sway/language",
{% if yadm.hostname == "nomad" %}
//"custom/week",
"clock#dayshort",
{% else %}
"custom/week",
"clock#day",
{% endif %}
"clock"
],
"sway/mode": {
"format": "<span style=\"italic\">{}</span>"
},
"sway/scratchpad": {
"format": "{icon} {count}",
"show-empty": false,
"format-icons": ["", ""],
"tooltip": true,
"tooltip-format": "{app}: {title}"
},
"clock": {
"interval": 1,
"format": " {:%F %T}",
"tooltip-format": "<tt><small>{calendar}</small></tt>",
"calendar": {
"mode" : "year",
"mode-mon-col" : 3,
"weeks-pos" : "left",
"on-scroll" : 1,
"on-click-right": "mode",
"format": {
"months": "<span color='#ffead3'><b>{}</b></span>",
"days": "<span color='#ecc6d9'><b>{}</b></span>",
"weeks": "<span color='#99ffdd'><b>W{}</b></span>",
"weekdays": "<span color='#ffcc66'><b>{}</b></span>",
"today": "<span color='#ff6699'><b><u>{}</u></b></span>"
}
},
"actions": {
"on-click-right": "mode",
"on-click-forward": "tz_up",
"on-click-backward": "tz_down",
"on-scroll-up": "shift_up",
"on-scroll-down": "shift_down"
}
},
"clock#day": {
"interval": 60,
"format": " {:%a %B week:%V}"
},
"clock#dayshort": {
"interval": 60,
"format": " {:%a %B}"
},
"custom/week": {
"interval": 60,
"exec": "${HOME}/.config/sway/scripts/statusbar__day_of_the_week.sh",
"tooltip": false
},
"sway/language": {
"format": " {shortDescription}",
"tooltip-format": " {long}"
},
"cpu": {
"interval": 5,
"format": " {usage}% {avg_frequency} GHz",
"tooltip": true
},
"memory": {
"interval": 5,
"format": " {}%",
"tooltip-format": "Used: {used:0.1f} GiB\nAval: {avail:0.1f} GiB\nTotal: {total:0.1f} GiB"
},
"disk": {
"interval": 10,
"format": " {percentage_used}%",
"path": "/"
},
"temperature": {
"interval": 5,
{% if yadm.hostname == "saturn" %}
"hwmon-path": "/sys/class/hwmon/hwmon1/temp2_input",
{% endif %}
"format": " {temperatureC}°C"
},
{% if yadm.hostname == "saturn" %}
"temperature#gpu": {
"interval": 5,
"hwmon-path": "/sys/class/hwmon/hwmon3/temp1_input",
"format": " {temperatureC}°C"
},
{% endif %}
"backlight": {
// "device": "acpi_video1",
"format": " {percent}%"
},
"battery": {
"states": {
// "good": 95,
"warning": 30,
"critical": 15
},
"format": "{icon} {capacity}%",
"format-charging": " {capacity}%",
"format-plugged": " {capacity}%",
"format-alt": "{icon} {time}",
// "format-good": "", // An empty format will hide the module
// "format-full": "",
"format-icons": ["", "", "", "", ""]
},
"battery#bat2": {
"bat": "BAT2"
},
"network": {
// "interface": "wlp2*", // (Optional) To force the use of this interface
"interval": 5,
"family": "ipv4",
"format-wifi": " {essid} ({signalStrength}%)",
"format-ethernet": " {ipaddr}/{cidr}",
"tooltip-format": " {ifname} via {gwaddr}",
"format-linked": " {ifname} (No IP)",
"format-disconnected": " ⚠ Disconnected"
},
"pulseaudio": {
"scroll-step": 0,
"format": "{icon} {volume}% {format_source}",
"format-bluetooth": "{icon} {volume}% {format_source}",
"format-bluetooth-muted": " {icon} {format_source}",
"format-muted": " {format_source}",
"format-source": " {volume}%",
"format-source-muted": "",
"format-icons": {
"headphone": "",
"hands-free": "",
"headset": "",
"phone": "",
"portable": "",
"car": "",
"default": ["", "", ""]
},
"on-click": "pavucontrol"
}
}
style.css
* {
/* `otf-font-awesome` is required to be installed for icons */
font-family: FontAwesome, Noto Sans Mono;
font-size: 14px;
}
window#waybar {
background-color: rgba(43, 48, 59, 0.5);
border-bottom: 3px solid rgba(100, 114, 125, 0.5);
color: #ffffff;
transition-property: background-color;
transition-duration: .5s;
}
window#waybar.hidden {
opacity: 0.2;
}
/*
window#waybar.empty {
background-color: transparent;
}
window#waybar.solo {
background-color: #FFFFFF;
}
*/
window#waybar.termite {
background-color: #3F3F3F;
}
window#waybar.chromium {
background-color: #000000;
border: none;
}
button {
/* Use box-shadow instead of border so the text isn't offset */
box-shadow: inset 0 -3px transparent;
/* Avoid rounded borders under each button name */
border: none;
border-radius: 0;
}
/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */
button:hover {
background: inherit;
box-shadow: inset 0 -3px #ffffff;
}
#workspaces button {
padding: 0 5px;
background-color: transparent;
/*background-color: #64727D;*/
color: #ffffff;
}
#workspaces button:hover {
background: rgba(0, 0, 0, 0.2);
}
#workspaces button.visible {
background: rgba(0, 0, 0, 0.2);
}
#workspaces button.focused {
background-color: #64727D;
box-shadow: inset 0 -3px #ffffff;
}
#workspaces button.urgent {
background-color: #eb4d4b;
}
#mode {
background-color: #64727D;
border-bottom: 3px solid #ffffff;
}
#clock,
#custom-week,
#battery,
#cpu,
#memory,
#disk,
#temperature,
#backlight,
#network,
#pulseaudio,
#wireplumber,
#custom-media,
#tray,
#mode,
#idle_inhibitor,
#scratchpad,
#mpd,
#language {
padding: 0 10px;
color: #dcdccc;
/*background-color: rgba(41, 128, 185, 0.3);*/
background-color: rgba(17, 17, 17, 0.8);
border-top: 3px solid rgba(100, 114, 125, 0.8);
}
#window,
#workspaces {
margin: 0 4px;
}
/* If workspaces is the leftmost module, omit left margin */
.modules-left > widget:first-child > #workspaces {
margin-left: 0;
}
/* If workspaces is the rightmost module, omit right margin */
.modules-right > widget:last-child > #workspaces {
margin-right: 0;
}
#clock {
}
#custom-week {
}
#battery {
}
#battery.charging, #battery.plugged {
}
@keyframes blink {
to {
background-color: #ffffff;
color: #000000;
}
}
#battery.critical:not(.charging) {
background-color: #f53c3c;
color: #ffffff;
animation-name: blink;
animation-duration: 0.5s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
label:focus {
background-color: #000000;
}
#cpu {
min-width: 120px;
}
#memory {
}
#disk {
}
#backlight {
}
#network {
}
#network.disconnected {
}
#pulseaudio {
}
#pulseaudio.muted {
}
#wireplumber {
}
#wireplumber.muted {
}
#custom-media {
min-width: 100px;
}
#custom-media.custom-spotify {
}
#custom-media.custom-vlc {
}
#temperature {
}
#temperature.critical {
}
#tray {
}
#tray > .passive {
-gtk-icon-effect: dim;
}
#tray > .needs-attention {
-gtk-icon-effect: highlight;
}
#idle_inhibitor {
}
#idle_inhibitor.activated {
}
#mpd {
}
#mpd.disconnected {
}
#mpd.stopped {
}
#mpd.paused {
}
#language {
min-width: 50px;
}
#keyboard-state {
padding: 0 0px;
margin: 0 5px;
min-width: 16px;
}
#keyboard-state > label {
padding: 0 5px;
}
#keyboard-state > label.locked {
}
#scratchpad {
}
#scratchpad.empty {
background-color: transparent;
}
Inspiration
More can be found at r/unixporn, just look for sway
.