Adventures in Hyprland
Every once in a while, I’ll give Wayland another try. I’ve been using the i3 window manager for years, so my last attempt was another crack at using Sway as my Wayland Composer. I had put weeks of effort into getting Sway working for my general development workflow, but it was eventually frustrating and broken enough that I went back to using i3/X11. This year, I’ve decided to try Hyprland. With its pretty animations and visuals, I heard good things about this tiling window composer. A few months in and there are still some Wayland things that frustrate me, but Hyprland is far beyond my Sway experience. I’ve had to, once again, try to reconstruct my workflows and default applications, but overall I’ve made a lot more headway this time. Hyprland is usable enough that I want to try to continue using it for the foreseeable future.
Make Development Fun Again
The first version of Hyprland I tried opened with a background image of the project’s anime mascot. I loved the default colors and cute initial wallpaper, but the anime theme upset several users1 and was removed last year2. When I attempted to find a Void Linux package for Hyprland, I found a discussion complaining about how the developers were “pricks” and accused someone of having a “smooth brain” because they liked Rust3. These little snippets made me laugh, and I got the impression this was likely a fun open source project and a labor of love, vastly different from the cold and enterprise world open source software development has become. I’m glad I took the dive and gave Hyprland a try. Sadly, the project hasn’t been able to avoid attention from political actors. For now, I’ll focus on my experience, and cover more of the politics later on.
The Gotchas
I spent a lot of time on my Hyprland and Waybar configurations. I was happy to discover Conky now supports Wayland, and I used both Conky and Waybar for a pretty useful desktop. However, I ran into a couple of things I needed to work around to get the applications I use to work in Wayland, scale correctly and have access to other essential parts of my system via dbus
.
Unlocking Keystores
When using Sway, a lot of the default keyrings used by most Linux apps would not unlock. On i3/X11, I’d get popup dialogs to unlock the gnome-keyring or enter a PGP password. This doesn’t seem to popup on the Wayland tiling composers I’ve tried. Hyprland seemed to have the same problems at first, preventing messaging applications from loading saved credentials. I discovered if I ran seahorse
first to unlock my keystores, most applications that depend on gnome-keyring
now work fine.
Electron App Wrappers
I created wrappers for Electron apps I use so they utilize Wayland instead of X11. This usually involves adding the flags --enable-features=UseOzonePlatform --ozone-platform=wayland
. Element also has the environment setting XDG_CURRENT_DESKTOP=Unity
. At one point, it wouldn’t load correctly without this, although it doesn’t appear to need it anymore. There was a version of FreeTube that would crash when going fullscreen on Wayland4, but it was due to an Electron bug that was fixed5. This bug was supposedly fixed in Element as well6, yet I still encounter it in Element 1.11.76 when displaying a video fullscreen.
# Electron Wrapper scripts # ~/bin/freetube-wayland #!/bin/sh exec freetube-bin --enable-features=UseOzonePlatform --ozone-platform=wayland # ~/bin/element-wayland #!/bin/sh exec env XDG_CURRENT_DESKTOP=Unity element-desktop --enable-features=UseOzonePlatform --ozone-platform=wayland
Scaling
When I last tried Sway, it had horrific scaling for X11 applications, with no option to let those applications handle scaling on their own. I have the following lines in my hyprland.conf
to handle scaling on my monitors and to prevent Hyprland from scaling X11 applications:
monitor=HDMI-A-1,preferred,0x0,1.875 monitor=DP-1,preferred,0x1152,1.875 xwayland { force_zero_scaling = true }
This makes it easy for applications without Wayland support to handle their own scaling. Most tools allow you to zoom using a key combination (typically Ctrl+
) or by a configuration setting. Zoom can be set in IntelliJ/PyCharm using the following preference:
Thunderbird
Thunderbird’s reminders didn’t float properly. I added the following rules to get them to display correctly7:
windowrulev2 = float,class:^(thunderbird)$,title:^(.*)(Reminder)(.*)$
Replacing Old Tools and Workflows
In the best cases, migrating to Wayland/Hyprland just requires some custom configuration. In less than ideal situations, applications need to be replaced entirely. For the worst cases, an entire workflow may need to be thrown out. I experienced all of these possibilities when dealing with tasks as basic as taking screenshots and as advanced as clipboard management.
Screenshots
I still cannot get Flameshot to work on Hyprland. The tools grim
, slurp
and swappy
can be combined to capture a part of the screen. A delay can be inserted using sleep
and placed in a script like the following:
#!/bin/sh sleep 2; grim -g "$(slurp)" - | swappy -f -
However, you cannot use this to capture most popup or context menus. For that, you need to capture the active window using a script such as the following:
#!/bin/sh sleep 2; grim -g (hyprctl -j activewindow | jq -r '"\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"') - | swappy -f -
swappy
is a nice tool. I’m thankful it exists. However, it can only save images into a default location. If you want to save images to a specific location, you need to prompt for the filename first using a tool like zenity
8. It also cannot crop images. Although there are workarounds for cropping9, I found it easier to just capture the active window and open the result in Gimp.
Screenshots are still an area where Hyprland (and Wayland composer in general) still suffer. Although, I’ve gotten by for several months using a combination of grim
, slurp
and swappy
, it’s still a hacky and frustrating solution; a far cry from what comes out-of-the-box with Flameshot.
Supervisord
When using my KVM switch to jump between machines, switching back to Hyprland would often result in applications crashing. Usually it was just my status bar or wallpaper changer. Restarting all of them became tedious, so I configured Hyprland to launch supervisord
as my process manager. The following is an example configuration file I placed in ~/.config/hypr/supervisord.conf
. It has a process group called monitors
, allowing me to easily restart applications that commonly crash on monitor disconnects.
[supervisord] logfile = /tmp/hypr-services/supervisor.log pidfile = /tmp/hypr-services/supervisor.pid childlogdir = /tmp/hypr-services/log/ [unix_http_server] file=/tmp/hypr-services/supervisord.sock [supervisorctl] serverurl = unix:///tmp/hypr-services/supervisord.sock username = supervisor password = <insert a secret password> [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface [group:monitors] programs=wallpaper,conky,waybar [program:wallpaper] command = /home/(username)/.cargo/bin/wpaperd [program:conky] command = /usr/bin/conky [program:rgb] command = /usr/bin/openrgb --startminimized [program:waybar] command = /usr/bin/waybar [program:clipboard] command = wl-paste --watch cliphist store [program:notifications] command = /usr/lib64/xfce4/notifyd/xfce4-notifyd [program:idle] command = /usr/bin/hypridle
I’ve added the following to ~/.config/hypr/hyprland.conf
to ensure supervisord
is launched one at startup.
exec-once = mkdir -p /tmp/hypr-services/log/ && /usr/bin/supervisord -c /home/(username)/.config/hypr/supervisord.conf
I then add the following alias
to my shell, so that I can easily run supervisord
commands with the alias hctl
:
alias hctl 'supervisorctl -c ~/.config/hypr/supervisord.conf'
Status Bars
On i3, I was using i3status
for my workspace bar. I had to create a new configuration to get something equivalent using waybar
.
The following is my configuration. I use the tool wttrbar to pull Weather information.
{ "layer": "top", "position": "bottom", "modules-left": [ "hyprland/workspaces", "custom/right-arrow-dark", "hyprland/window", ], "modules-center": [ "custom/left-arrow-dark", "custom/weather", "custom/left-arrow-light", "custom/left-arrow-dark", "clock#1", "clock#2", "clock#3", "clock#4", "clock#5", "custom/right-arrow-dark" ], "modules-right": [ "cava", "custom/left-arrow-dark", "network#speed", "custom/left-arrow-light", "custom/left-arrow-dark", "network#4", "network#6", "custom/left-arrow-light", "custom/left-arrow-dark", "tray" ], "custom/weather": { "format": "{}", "tooltip": true, "interval": 3600, "exec": "/home/(username)/.cargo/bin/wttrbar --location Chattanooga", "return-type": "json" }, "custom/left-arrow-dark": { "format": "", "tooltip": false }, "custom/left-arrow-light": { "format": "", "tooltip": false }, "custom/right-arrow-dark": { "format": "", "tooltip": false }, "custom/right-arrow-light": { "format": "", "tooltip": false }, "cava": { "framerate": 30, "autosens": 1, "bars": 10, "lower_cutoff_freq": 50, "higher_cutoff_freq": 10000, "method": "pulse", "source": "auto", "stereo": false, "reverse": false, "bar_delimiter": 0, "monstercat": false, "waves": true, "noise_reduction": 0.77, "input_delay": 2, "format-icons" : ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" ], "actions": { "on-click-right": "mode" } }, "hyprland/workspaces": { "format": "{name}", "on-scroll-up": "hyprctl dispatch workspace e-1", "on-scroll-down": "hyprctl dispatch workspace e+1" }, "hyprland/window": { "format": "👉 {}", "rewrite": { "(.*) — Mozilla Firefox": "🌎 $1", "(.*) - fish": "> [$1]" }, "separate-outputs": true }, "clock#1": { "format": " Seattle: {:%H:%M} ", "timezone": "America/Los_Angeles", "tooltip": false }, "clock#2": { "format": " Chicago: {:%H:%M} ", "timezone": "America/Chicago", "tooltip": false }, "clock#3": { "format": " New York: {:%H:%M} ", "timezone": "America/New_York", "tooltip": false }, "clock#4": { "format": " London: {:%H:%M} ", "timezone": "Europe/London", "tooltip": false }, "clock#5": { "format": " Auckland: {:%H:%M} ", "timezone": "Pacific/Auckland", "tooltip": false }, "network#speed" : { "format": " {bandwidthUpBytes} / {bandwidthDownBytes} ", "interface": "enp1s0f1", "interval": 1 }, "network#4" : { "format": " {ipaddr} ", "interface": "enp1s0f1", "interval": 1, "family": "ipv4", }, "network#6" : { "format": " {ipaddr} ", "interface": "enp1s0f1", "family": "ipv6", }, "tray": { "icon-size": 15, "show-passive-items": true, } }
In the above example, I’ve included the cava
widget, even though it’s not supported in the version of waybar
available in Gentoo. Currently, there is only a package for media-sound/cava
, and not for building a shared library. I have a local Gentoo Portage overlay located in /usr/local/portage
, and created media-sound/libcava
, based off of the media-sound/cava
ebuild, with the following:
EAPI=8 inherit meson DESCRIPTION="Console-based Audio Visualizer for Alsa" HOMEPAGE="https://github.com/karlstav/cava/" SRC_URI=" https://github.com/LukashonakV/cava/archive/refs/tags/${PV}.tar.gz -> ${P}.tar.gz " LICENSE="MIT Unlicense" SLOT="0" KEYWORDS="amd64 x86" IUSE="alsa jack +ncurses pipewire portaudio pulseaudio sdl sndio" RDEPEND=" dev-libs/iniparser:4 sci-libs/fftw:3.0= alsa? ( media-libs/alsa-lib ) jack? ( virtual/jack ) ncurses? ( sys-libs/ncurses:= ) pipewire? ( media-video/pipewire:= ) portaudio? ( media-libs/portaudio ) pulseaudio? ( media-libs/libpulse ) sdl? ( media-libs/libglvnd media-libs/libsdl2[opengl,video] ) sndio? ( media-sound/sndio:= ) " DEPEND="${RDEPEND}" BDEPEND=" virtual/pkgconfig sdl? ( dev-build/autoconf-archive ) " S="${WORKDIR}/cava-${PV}" PATCHES=( "${FILESDIR}"/${PN}-0.8.0-gentoo-iniparser4.patch ) src_prepare() { default echo ${PV} > version || die } src_configure() { local emesonargs=( ) meson_src_configure }
I then copied the ebuild for gui-apps/waybar
to my local overlay, and modified it so -Dcava=disabled
was now -Dcava=enabled
# diff /usr/portage/gui-apps/waybar/waybar-0.10.3.ebuild /usr/local/portage/gui-apps/waybar/waybar-0.10.3.ebuild 80c80 < -Dcava=disabled --- > -Dcava=enabled
Finally, I used the following as my waybar
stylesheet, located in ~/.config/waybar/style.css
.
@define-color main-background #003566; @define-color second-background #001d3d; @define-color main-text #ade8f4; @define-color second-text #bde0fe; @define-color alert-color #c1121f; @define-color highlight #ffd60a; * { font-size: 12px; font-family: monospace; min-height: 0; } window#waybar { background: @second-background; color: @main-text; } #custom-right-arrow-dark, #custom-left-arrow-dark { color: @main-background; } #custom-right-arrow-light, #custom-left-arrow-light { color: @second-background; background: @main-background; } #workspaces, #clock.1, #clock.2, #clock.3, #clock.4, #clock.5, #network.4, #network.6, #network.speed, #custom-weather, #cava, #tray { background: @main-background; } #tray, #window { padding-left: 10px; } #network.speed { min-width: 180px; color: @second-text; } #network.4, #network.6 { color: @second-text; } #custom-weather { padding: 0 5px; } #workspaces button { padding: 0 2px; color: #fdf6e3; } #workspaces button.active { color: @highlight; border-bottom: 2px solid @highlight; } #workspace button.urgent { color: @alert-color; } #workspaces button:hover { box-shadow: inherit; text-shadow: inherit; } #workspaces button:hover { background: @main-background; border: #1a1a1a; padding: 0 3px; } #cava { background: @second-background; padding-right: 10px; }
The only minor issues I seem to have with this configuration is the style for #workspace button.urgent
. With the i3 window manager, a workspace name on the status bar would turn red, indicating a notification. These would trigger when chat programs received messages, or a link was opened in a web browser. I’m not sure if or how similar notifications are implemented in Wayland. Even though I’m using Wayland versions of web browsers and chat applications, Waybar doesn’t appear to be showing notifications. Either my CSS configuration is incorrect or the events haven’t been implemented between these programs and Wayland/Hyprland.
Clipboard Management
On i3, I had been using parcellite for clipboard management. In the supervisord
configuration listed previously, I had a section to launch wl-paste --watch cliphist store
as a background daemon. Cliphist is a clipboard history manager for Wayland. The following line in my ~/.config/hypr/hyprland.conf
attaches a keybinding to bring up my clipboard history in a wofi
menu selector:
bind = Ctrl_Alt, H, exec, cliphist list | wofi --sort-order=default --show dmenu | cliphist decode | wl-copy
Transparent Inactive Windows
With i3, I used compton
to make inactive windows transparent, using the following configuration:
# compton.conf mark-ovredir-focused = true; inactive-opacity = 0.8; menu-opacity = 0.9;
To get a similar effect with Hyprland, the following rule can be added to hyprland.conf
10:
windowrulev2 = opacity 1.0 0.8,class:.*
Wofi
On i3, I had been using rofi
as my launcher and menu selection tool. Although I can create rules for rofi
to float and center correctly, I had issues with it not correctly getting focus and having blurry text. I switched to wofi, and equivalent program for Wayland. Wofi does look better, and the text is considerably more crisp. However, it is sometimes slower than rofi
when loading menus.
I use splatmoji as my emoji picker, and it can be configured for wofi
using the following splatmoji.config
rofi_command=wofi -dmenu -p '' -i -monitor -2 xsel_command=wl-copy xdotool_command=xdotool sleep 0.2 type --delay 100
I used a script called quickswitch.py
to search and switch to a window using its title. I found the following script that achieves the same thing in Hyprland using wofi
and just a few lines11.
#!/bin/bash WINDOW=$(hyprctl clients | grep "class: " | awk '{gsub("class: ", "");print}' | wofi --show dmenu) if [ "$WINDOW" = "" ]; then exit fi hyprctl dispatch focuswindow $WINDOW
Scratchpad
I use QOwnNotes as my note-taking program. On i3, I was able to place this program on a scratchpad workspace that I could activate with a hotkey. Hyprland also supports a scratchpad workspace, but by default it takes up the entire screen. I found the following settings to customize my scratchpad in Hyprland. However, it doesn’t seem like it’s possible to focus on, or interact with, any window that’s behind the scratchpad12.
dwindle { special_scale_factor=0.60 } bind = $mainMod, S, togglespecialworkspace, magic bind = $mainMod SHIFT, S, movetoworkspacesilent, special:magic
Issues
- If I configure my monitors to go into standby using DPMS, one of my monitors will power down while the other will blank for a few seconds before turning back on. This is a known issue. It has some workarounds (none of which I could get to work), and no solutions13.
- Monitor disconnects and reconnects can result in some windows not being scaled correctly, causing them to appear blurry14. I’ve found moving a window to another monitor and back will correct the scaling, but this can be tedious and there don’t appear to be any workarounds yet.
- Drag and drop between file managers like Dolphin and various programs (both X11 and Wayland) seems to be inconsistent and unreliable.
- Clicking on a link will sometimes open that link in an active web browser, and sometimes I’ll get an error saying a browser is already open.
Support
Hyprland does have an official website with excellent documentation. Unfortunately, it does not have a public web forum. Instead, they rely on Discord and Matrix for chat. I’ve been frustrated by other projects that use Discord for support, because it’s closed source15 and makes searching for known solutions much more difficult16.
The Matrix chat isn’t very active, but there are helpful people on it that do occasionally read and respond to messages. Although the Discord chat seems more active, it requires phone number verification to participate, which is an instant dealbreaker for me.
The Political Landscape of Open Source Projects
Most projects need a starting point, and it’s difficult to create a new Wayland composer from scratch. Hyprland used a library called wl-roots
. The original creator of wl-roots
has accused Hyprland of being “developed entirely in the high school boy’s locker room” and being “bigoted, hateful, and obnoxious17.” Hyprland’s issue tracker has been used to accuse developers of thought-crimes by posting screenshots of their Discord chat18, where they mostly joked about exclusive inclusivity.
The creator of wl-roots
wrote an article about how Hyprland was a toxic community19. Vaxry, the creator of Hyprland, wrote a very detailed response addressing all allegations made against the Hyprland community20. Eventually, Vaxry wrote his own Code of Conduct and added it to the Hyprland codebase21.
I don’t want to go into all the muddy details and accusations, as it’s quite exhausting. Hyprland fulfilled a need that was deeply missing in the world of tiling window composers for Wayland. The moment it got successful, it was attacked by people from entirely different projects, who didn’t like the political views or chat messages from other Hyprland contributors. Accusations of hatefulness have become a political tool used by activists to control, manipulate and destroy open source software projects22.
So far, Hyprland seems to have weathered the storm and grown in popularity. It has successfully removed all dependencies on wl-roots
in the 0.42.0 release23. However, the latest version still seems to have many of the issues I’ve mentioned here, leading me to believe they might be inherent to writing Wayland composers in general and not wl-roots
.
Still, I hope the best for the project and that it continues to improve. It will be another test to see if open source projects can truly weather the coming political and ideological storms.
Summaries
As a quick recap, here is a list of applications I had to migrate from, and what I replaced them with, when going from i3 to Hyprland.
- Clipboard Manager -
parcellite
replaced with a combination ofcliphist
,wofi
,wl-copy
,wl-paste
and specific keybindings - Quick Launch Menus -
rofi
replaced withwofi
for quick menus used to launch programs, search through running windows and select emojis - Screenshots - Flameshot replaced by stitching together
grim
,slurp
, andswappy
- Status Bars - Waybar replaced i3status, while Conky was updated to use Wayland
- Transparent Windows - What was previously provided by
compton
can be configured directly within Hyprland - Wallpapers - Wpaperd replaced custom wallpaper scripts
The follow is a recap of things that are still broken or not great.
- Librewolf, Waybar, Conky and Wpaperd might crash on monitor disconnects - If you disconnect a monitor (or use a KVM switch), these four programs sometimes crash. Other times they don’t. Librewolf and Conky did not have any crashing issues under
i3
when used with my KVM switch. - Hyprland cannot gracefully handle monitor disconnects - The window manager moves everything off of a disconnected monitor to a connected one. Just like Sway, there’s no way to configure it to gracefully ignore disconnected monitors.
- dpms is broken on one monitor - A known issue that is probably more the fault of my monitor than Hyprland, but still one that affects a lot of people
- grim+swappy are still inferior to Flameshot - They work for many of my use cases. So I can continue to work around and improve my workflow for screenshots.
- No workspace level notification - Although there are CSS codes and APIs for workspace notifications in Wayland, they don’t appear to be implemented in any of the applications I use, or Waybar doesn’t display them correctly.
- Blurry Windows - When disconnecting a monitor or coming out of DPMS, some windows will not be scaled correctly and will appear blurry.
Conclusions
There are still some minor issues here and there with Hyprland. Small things like graphical glitches or momentary smearing during animations and transitions don’t bother me that much. The window manager is surprisingly mature and functional compared to Sway. The biggest functional issue I have is with monitor disconnects and my KVM switch, which are incredibly annoying. Still, I’ve been using Hyprland/Wayland for several months now, and this is the first time I haven’t immediately felt like calling it quits and going back to X11.
Although I have been using Hyprland full-time for months, the issues I’ve stated have really started to annoy me during day-to-day use. My work laptop is still on i3, and I’d be very hesitant to try Hyprland on that device, considering potential issues with video calls and screen sharing.
I recently started using wezterm
on my work laptop. Although it claims to have Wayland support, it fails to launch in Hyprland. I did a few cursory searchers to diagnose the issue, but didn’t find anything that worked. This was yet another example of how I couldn’t even try a terminal without running into issues on a Wayland composer. Despite all the advances and amazing work Hyprland has made, Wayland composers are still a frustrating mess that require massive changes to workflows, and replacing so much existing tooling, that I hesitate to see any worthwhile benefit for my use cases.
For the time being, my primary machine will likely be going back to i3 and X11. I will keep experimenting with Hyprland on my laptop and secondary devices. I hope for the day when Hyprland is mature enough to be a trouble free daily driver. Until that day comes, I hope the developers of Hyprland can keep themselves safe from the toxic elements arising within the Open Source Community that seek to use politics to undermine rising projects.
-
Default Anime Wallpaper. 25 July 2023. u/Heavy_Aspect_8617. r/hyprland. Reddit. ↩
-
Completely disable hypr-chan #2930. 9 August 2023. REALERvolker1. ↩
-
Has anyone managed to get Hyprland working on void?. 22 Feburary 2023. u/[deleted user] r/voidlinux. Reddit. ↩
-
Bug: FreeTube crashes when being maximized or fullscreened (Wayland) #5304. pm4rcin. FreeTubeApp / FreeTube ↩
-
Crash when fullscreening on Wayland #109. boredsquirrel. flathub / io.freetubeapp.FreeTube. ↩
-
Element desktop screen share crashes app on Wayland #1047. 30 June 2023. element-hq/element-desktop ↩
-
How to handle window popups?. 21 July 2023. u/lqlarry. r/hyprland. Reddit. ↩
-
Ask where to save files. #125. 1 January 2022. migonos0. Github. ↩
-
Cut/Crop Image #155. 30 October 2023. tkna91. Github. ↩
-
A question about opacity. 17 May 2023. u/cknyakina. r/hyprland. Reddit ↩
-
Get open windows list #830. 11 Oct 2022. mshzsh. Github. ↩
-
Specify scratchpad/special workspace size. 5 December 2023. u/SkinwalkerFanAccount r/Hyprland. Reddit ↩
-
Monitors don’t stay off after “hyprctl dispatch dpms off” or “hyprctl dispatch dpms” #5557. 11 April 2024. RedIODev. Github. ↩
-
monitor on/off makes windows blurry #6560. 17 June 2024. andresilva. Github. ↩
-
Stop Using Discord. Retrieved 5 September 2024. ↩
-
Stop using Discord for anything else than just chatting. Stop dumping knowledge into a black hole. Use forums.. 30 March 2024. @didier@malenfant.net ↩
-
Hyprland: the only Wayland compositor developed entirely in the high school boy’s locker room. 17 September 2023. @drewdevault@fosstodon.org archive ↩
-
New information for Vaxry’s toxicity: He is a Nazi #3775. 5 November 2023. cinnabartalli. Github. (archive only / original deleted) ↩
-
Hyprland is a toxic community. 17 September 17, 2023. DeVault. ↩
-
Misinformation about the Hyprland community. 17 September 2024. Varxy’s Blog. ↩
-
Add a CoC #3366. 20 September 2023. vaxerski. Github. ↩
-
Inclusivity Activists are Destroying Open Source. 23 August 2024. Lunduke. ↩
-
At last, independence with 0.42.0!. 7 August 2024. Hyprland. ↩