Pete's Log: Sway Sway Sway

Entry #2050, (Coding, Hacking, & CS stuff)
(posted when I was 43 years old.)

It's been a few weeks now since I switched to Sway and I think I'm starting to hit my stride in this new environment. I finally got the last "big" item on my wish list figured out, so I figured I'd document where I'm at, only covering things that are changed from the default Debian Sway config.

My workspace 1 hasn't changed much since my last Sway screenshot, but here it is

Pete's Sway Workspace 1

Firefox

Launching URLs

The thing I figured out today is something that actually bothered me in GNOME too, which is that when I open a link from an application, if I don't have Firefox open in the current workspace but I do have it open in another workspace, it'll open in a new tab in that workspace. I want a new window in the current workspace. But also if there's already a Firefox window in the current workspace, then I do want a new tab in that existing window. I could not find anyone else trying to accomplish this, so I made a Sway-specific solution for myself. Not sure if it's a good solution, but so far it does exactly what I want, which pleases me. Here's how it works:

First, I have a little shell script that launches Firefox differently depending on there being a window on the current workspace:

#!/usr/bin/bash ffcmd=/opt/firefox/firefox-bin ws=$(swaymsg -r -t get_workspaces| jq -r '.[]|select(.focused)|.name') ff=$(swaymsg -r -t get_tree| jq -r '..|select(.type?=="workspace" and .name?=="'$ws'")|.nodes[],.floating_nodes[]|select(.app_id=="firefox")|.app_id'|head -1) if [[ $ff == "firefox" ]]; then $ffcmd $1 else $ffcmd --new-window $1 fi

Then I created a userapp-Firefox-newwindow.desktop file for my launcher in ~/.local/share/applications:

[Desktop Entry] Encoding=UTF-8 Version=1.0 Type=Application NoDisplay=true Exec=/home/prijks/.local/bin/firefox-launcher.sh %u Name=Firefoxnw Comment=Custom definition for Firefox MimeType=x-scheme-handler/unknown;x-scheme-handler/about;x-scheme-handler/https;x-scheme-handler/http;text/html;

Finally, I used xdg-settings to configure my launcher as the default web browser:

xdg-settings set default-web-browser userapp-Firefox-newwindow.desktop

Now links open in Firefox just like I want them to. And there is probably a much easier way of accomplishing this.

Enabling Wayland in Firefox

I wanted Firefox to use native Wayland instead of XWayland, and apparently it's as easy as setting the MOZ_ENABLE_WAYLAND environment variable to 1. Getting that environment variable set globally was much harder than I anticipated, though. The combination of systemd+logind+Wayland means most of the files I'm familiar with do not get read. But finally I found that creating a ~/.config/environment.d/60-firefox.conf file with the contents MOZ_ENABLE_WAYLAND=1 did the trick. The "60-" at the start of the filename is important - not the number itself, but the existence of a number. Without it, it won't get processed.

Getting Firefox running in native Wayland also solved another issue - not having swayidle blank the screen if a video is playing in Firefox. Wayland has an "inhibit_idle" flag that windows can set and Firefox in native Wayland will set that flag. Neat.

Keyboard

The keyboard is configured via input statements in the Sway config file. These statements can target a specific device by ID, but they can also target everything with a "*" or specific input types with "type:keyboard" for example. All my keyboard configurations use "type:keyboard".

Swapping Control and Caps

This one is a less intrusive modification of the keyboard than Dvorak. And since I never use capslock, I opted for the option to make capslock an additional control key instead of swapping the two. It's been a while since I've had my capslock key be a control key and the muscle memory is slow to return so far.

input "type:keyboard" xkb_options "ctrl:nocaps"

Turning numlock on

It took me a few days before I realized numlock was off every time I signed in. Rarely do I want numlock off. Luckily, it's easy enough to configure to be on by default.

input "type:keyboard" xkb_numlock enabled

Adding and switching keyboard layouts

Sometimes I want to type auf deutsch, which is much gemütlicher if I can swap to the German layout. Takes two steps: add the layout, and pick a hot key to switch. I was originally going to pick win+space since that's what Gnome used, but win+space is already bound to a different Sway command, so I opted for ctrl+alt instead, since that felt familiar from Windows.

input "type:keyboard" xkb_layout us,de input "type:keyboard" xkb_options "grp:ctrl_alt_toggle"

Bringing it all together

Multiple input statements with the same target can be combined in braces after the target name. Additionally, if using multiple xkb_options, they need to be comma-separated in the same line, otherwise only the last xkb_options specified will apply. So my config file actually looks like this instead of the four lines above:

input "type:keyboard" { xkb_numlock enabled xkb_layout us,de xkb_options "ctrl:nocaps,grp:ctrl_alt_toggle" }

Waybar

I spent just a short while configuring the default sway bar before realizing waybar seems to be the popular way to go. My waybar shows the workspaces on the top left, the date and time in the top center, and looks like this in the top right:

Top right of Pete's Sway screen - waybar modules

The volume, memory, CPU, and disk are all built-in waybar modules. On the very left is an indicator of what's in my scratchpad (see below) and on the right is an indicator of my current keyboard layout and the Copyq icon in the waybar tray.

The scratchpad indicator is based on one posted to Reddit a couple weeks ago. The main change I made was to have it always display instead of only when there are windows in the scratchpad.

The keyboard layout indicator took a little time and is based on one I found in the comments of a pull request to add a builtin keyboard layout indicator to Waybar. There are a number of issues and pull requests related to this, but as far as I can tell, there's no builtin support yet. But this custom module is working well for me so far.

My favorite part is living in the future where I can use emoji in shell scripts.

#!/usr/bin/bash # based on https://github.com/Alexays/Waybar/pull/85#issuecomment-560100037 swaymsg -t get_inputs | jq -rcM --argjson icons '["🇺🇸","🇩🇪"]' \ "first(.[] | select(.identifier == \"$1\" and .type == \"keyboard\")) \ | \$icons[.xkb_active_layout_index]" swaymsg -mrt subscribe '["input"]' | jq -rcM --unbuffered --argjson icons '["🇺🇸","🇩🇪"]' \ "select(.change == \"xkb_layout\") | .input | select(.identifier == \"$1\" and .type == \"keyboard\") \ | \$icons[.xkb_active_layout_index]"

This is then run from the Waybar config file:

"custom/layout": { "format": "{}", "exec": "~/.config/waybar/kblayout.sh '5426:552:Razer_Razer_BlackWidow_Elite_Keyboard'", "tooltip": false },

Clipboard

I am still trying to figure out the clipboard situation. I'm still figuring out when something will get copied to the clipboard I can access via middle mouse button or shift-insert and when it will get copied to the clipboard that uses app-specific keyboard shortcuts for pasting. I'm also trying out a tool called CopyQ which keeps a clipboard history that is handy.

I did confuse myself the first time I launched CopyQ, because I had the following in my clipboard but had forgotten about it and thought CopyQ was failing to connect to the clipboard somehow.

CopyQ with the text "fail to list events: Unauthorized" on the clipboard

Scratchpad

I'm really liking the scratchpad concept. I like having a couple tiled terminals open and then having a floating Firefox window that I send to the scratchpad when I'm not looking at it.

The only thing that confused me at first is that there seems to be no way to remove a window from the scratchpad. The command to bring a window back from the scratchpad will hide any other scratchpad window before bringing another one back, so you only ever get one scratchpad window on screen at a time. So when I accidentally send a window to the scratchpad it belongs there for the rest of its life. Browsing the manual and source code seem to confirm there is no way to de-scratchpad a window once it's been sent there. Luckily as the key bindings have become more familiar, it's become rare that I accidentally scratchpad a window I didn't want to.

media keys

Getting the media keys on my keyboard to do what I want took a little experimenting but wasn't too bad.

bindsym XF86AudioMute exec pactl set-sink-mute @DEFAULT_SINK@ toggle bindsym XF86AudioRaiseVolume exec ~/.config/sway/increasevolume.sh bindsym XF86AudioLowerVolume exec pactl set-sink-volume @DEFAULT_SINK@ -2% bindsym XF86AudioPlay exec mpc toggle bindsym XF86AudioPrev exec mpc prev bindsym XF86AudioNext exec mpc next

The reason for a shell script for raising volume was that pactl won't reduce the volume below 0, but will gladly keep raising it way above 100% which starts sounding awful real quick. So increasevolume.sh just checks the current volume and only raises it if it's below 100%.

Screen

Suspending when screen is off

I don't have swayidle lock my screen, just turn it off and on. esgerbeastie also doesn't suspend automatically, only when I push the power button. Often enough I will hit the power button to suspend when the screen is already off, and when I do that, it would not come back on after resuming. I found I had to add an after-resume command:

exec swayidle -w \ timeout 300 'swaymsg "output * dpms off"' resume 'swaymsg "output * dpms on"' \ after-resume 'swaymsg "output * dpms on"'

screenshots

There are a lot of tools and opinions out there that people use for screenshots in Sway. So far I'm keeping it real simple:

bindsym Print exec grimshot save screen bindsym $mod+p exec grimshot save active bindsym $mod+Shift+p exec grimshot save area

I think those mimic the Windows screenshot keys but then just save the selected screen/window/region to my home directory. Haven't found that I need more yet. Maybe some day I will.

Final Thoughts

Sway is apparently very closely based on the i3 window manager, but for Wayland. I've never used i3 or any tiling window manager before, so I can't compare it to those. It was a slight learning curve at first, but once I understood what was going on, I quickly came to love the tiling paradigm.

The Sway and Waybar man pages are excellent. (Remember to man 5 sway.) Finding things via search engines is difficult, since Microsoft also has a product called Sway. Sometimes adding Wayland or changing Sway to Swaywm helps, but it's still hit or miss. Browing the swaywm subreddit has been a good source of ideas.

I do think I should at some point disconnect my mouse to get more in the habit of using they keyboard to navigate, but even without forcing myself to I've been slowing improving in that regard.

As usual, my dotfiles are on codeberg.