Hyprland

From ArchWiki

Hyprland is a wlroots-based tiling Wayland compositor written in C++. Noteworthy features of Hyprland include dynamic tiling, tabbed windows, a clean and readable C++ code-base, and a custom renderer that provides window animations, rounded corners, and Dual-Kawase Blur on transparent windows. General usage and configuration is thoroughly documented at Hyprland wiki.

Installation

Install one of the following:

Hyprland bundles its own version of wlroots, which closely follows wlroots-gitAUR. This improves stability, while also avoiding dependency conflicts with other wlroots-based compositors.

Note:
  • NVIDIA GPU users should also make sure to follow the NVIDIA specific page on the upstream Wiki before trying to launch Hyprland. Failure to do so will likely result in many bugs including not being able to log in, flashing windows and high CPU usage.
  • Using an NVIDIA GPU with Hyprland is unsupported. Many users have had success but if something is broken then you are on your own.

Configuration

Note: Most of the options listed (and more) are explained in detail on the upstream Wiki variables page.

Configuration is done through a single configuration file, hyprland.conf, though it supports splitting the configuration into multiple files and including them in hyprland.conf. The default file is /usr/share/hyprland/hyprland.conf and, after logging in for the first time, ~/.config/hypr/hyprland.conf.

hyprland.conf includes directives to configure your devices (keyboards, mice, trackpads, monitors), as well as settings for animations, decorations, layout, etc. You can set key bindings, window rules, and execute commands (either once or each time) the configuration is reloaded.

The configuration is automatically reloaded each time you update the file. You can also use hyprctl reload for the same effect. For some settings (particularly input settings), you may have to restart your Hyprland session.

Settings can also be changed on the fly with hyprctl but they will not be saved.

Keyboard

Keymap

By default Hyprland will use US Qwerty, you can configure it as follows:

~/.config/hypr/hyprland.conf
# German Colemark layout
input {
    ...
    kb_layout = de
    kb_variant = colemark
    ...
    }

See upstream's Wiki for all available options.

Note: Hyprland will override locale definitions so its necessary to change keymap if you do not use a US layout keyboard.

Typematic delay and rate

While Xorg users will be used to having this setting defined at the server level, on Wayland each compositor handles it on its own:

~/.config/hypr/hyprland.conf
# Repeat rate and delay
input {
    ...
    repeat_rate = 25
    repeat_delay = 600
    ...
    }

Keyboard backlight

Using keyboard brightness controls in Hyprland is possible by making use of XF86KbdBrightness

Install brightnessctl then add the following binds:

~/.config/hypr/hyprland.conf
# Keyboard backlight
bind = , xf86KbdBrightnessUp, exec, brightnessctl -d *::kbd_backlight set +33%
bind = , xf86KbdBrightnessDown, exec, brightnessctl -d *::kbd_backlight set 33%-

It is also possible to have on-screen notifications that fire when changes are made.

Media keys

Using keyboard media controls in Hyprland is possible by making use of XF86Audio keysyms and an external application like pavucontrol or pamixer and playerctl.

~/.config/hypr/hyprland.conf
# Volume and Media Control
bind = , XF86AudioRaiseVolume, exec, pamixer -i 5 
bind = , XF86AudioLowerVolume, exec, pamixer -d 5 
bind = , XF86AudioMicMute, exec, pamixer --default-source -m
bind = , XF86AudioMute, exec, pamixer -t
bind = , XF86AudioPlay, exec, playerctl play-pause
bind = , XF86AudioPause, exec, playerctl play-pause
bind = , XF86AudioNext, exec, playerctl next
bind = , XF86AudioPrev, exec, playerctl previous

It is also possible to have on-screen notifications that fire when changes are made.

Touchpad gestures

Being a Wayland compositor, Hyprland has full support for touchpad gestures though they are disabled by default. To enable them, make the following edit:

~/.config/hypr/hyprland.conf
# Enable touchpad gestures
gestures {
    workspace_swipe = true
    workspace_swipe_fingers = 3
}

See the upstream Wiki for all available options.

Display settings

Screen sharing

See Screen-sharing

As a wlroots-based compositor, Hyprland can utilize xdg-desktop-portal-wlr to enable screen capture in a range of applications by way of xdg-desktop-portal.

Hyprland also maintains xdg-desktop-portal-hyprland, a fork of the wlr portal with added functionality including region sharing, window sharing, and a graphical picker utility. Usage of the portal is further documented in the Hyprland wiki

Setting screen resolution

Hyprland will try to detect your screen resolution automatically however in some cases it will fail and default to a fail-safe, usually if there are multiple screens present or if you have a hybrid laptop. If everything on your screen is huge then you need to configure your default monitor and resolution.

First find your default monitor using hyprctl:

$ hyprctl monitors
Monitor eDP-1 (ID 0):
        1920x1080@144.003006 at 0x0
        description: Chimei Innolux Corporation 0x153C (eDP-1)
        ...

Then add your monitor to the configuration:

~/.config/hypr/hyprland.conf
...
# Monitor details
monitor=eDP-1,1920x1080@144,0x0,1
...

0x0 is a position offset used for multi screen setups and the final 1 is the screen scaling factor.

Screen backlight

Install brightnessctl then add the following binds:

~/.config/hypr/hyprland.conf
# Screen brightness
bind = , XF86MonBrightnessUp, exec, brightnessctl s +5%
bind = , XF86MonBrightnessDown, exec, brightnessctl s 5%-

It is also possible to have on-screen notifications that fire when changes are made.

Usage

Starting

It is currently recommended to start Hyprland from a TTY.

$ Hyprland

While launching from a display manager is not officially supported, users have reported success launching from GDM, SDDM, and others. The hyprland package contains a display manager entry, and all Hyprland AUR packages will generate one automatically.

Both methods provide identical results, plus or minus a few environment variables and services.

Auto login

Users can automatically login by using a display manager or adapting the method described in Xinit#Autostart X at login.

hyprctl and IPC

hyprctl is a command line utility that comes installed with Hyprland to communicate with the display server. It allows you to dispatch commands to the server (equivalent to commands in the configuration file, but with a slightly different syntax), set keywords, send queries and request information. See the full documentation.

Hyprland also exposes 2 UNIX Sockets for controlling and getting information about Hyprland via code or command-line utilities. These sockets broadcast events on focus change (windows, workspaces, monitors), creation of windows/workspace, and so on.

Both hyprctl and the IPC sockets can be effectively used in scripts to control Hyprland for complex tasks.

exec versus exec-once

When starting applications it is important to use the correct type of dispatcher, using exec incorrectly can result in applications being started multiple times taking up system resources and in the worst cases, causing a race condition that can crash your system.

Note: As mentioned in #Configuration, Hyprland automatically parses hyprland.conf each time a change to the file is saved: do not use exec for everything. In most cases you should use exec-once to launch applications and daemons at boot, as this command will not run again with a reload, only use exec if you are absolutely sure you want the command to run again on every reload.

Setting environment variables

It is possible to set environment variables directly in hyprland.conf through the env keyword, which has a different syntax than the env UNIX command used by shells.

The differences are explained on the upstream Wiki.

Tips and tricks

Note:
  • For all below sections there will usually be more than one way of achieving a similar result, everything provided here is a basic example.
  • For a comprehensive list of alternatives refer to List of applications, a Hyprland specific list can be found on the upstream Wiki.

File manager

Hyprland requires a wayland-compatible external application if graphical file management is desired. Using thunar as an example, we simply need to assign it a keybind as follows:

~/.config/hypr/hyprland.conf
...
bind = SUPER, E, exec, thunar
...

Application launcher

Hyprland requires a wayland-compatible external application to launch applications. Using wofi as an example, we simply need to assign it a keybind as follows:

~/.config/hypr/hyprland.conf
...
bind = SUPER, F, exec, wofi
...

Idle

Hyprland requires a wayland-compatible external idle management daemon. The most common setup is swayidle and swaylock. You can lock your screen manually using a bind as follows:

~/.config/hypr/hyprland.conf
...
bind = SUPER, L, exec, swaylock -f -c 000000
...

Automatic screen locking and suspend

Create the following script:

~/.config/hypr/scripts/sleep.sh
swayidle -w timeout 300 'swaylock -f -c 000000' \
            timeout 600 'systemctl suspend' \
            before-sleep 'swaylock -f -c 000000' &
Tip:
  • You can adjust the timeout periods by editing the numerical values, in seconds. 300 is 5 minutes, 600 is 10 minutes etc.
  • The script must be executable.

Then call it:

~/.config/hypr/hyprland.conf
...
exec-once = ~/.config/hypr/scripts/sleep.sh
...

Turning off the screen using DPMS after a timeout period

Hyprland has a built in dispatcher to handle DPMS requests however using it as a direct keybind is not recommended, doing so will result in you not being able to turn the screen back on and will require you to reboot.

Edit the script from above and change it to read:

~/.config/hypr/scripts/sleep.sh
swayidle -w timeout 300 'swaylock -f -c 000000' \
            timeout 600 'hyprctl dispatch dpms off' \
            resume 'hyprctl dispatch dpms on' \
            timeout 900 'systemctl suspend' \
            before-sleep 'swaylock -f -c 000000' &
Tip: The hyprctl dispatch dpms on command must come directly after the hyprctl dispatch dpms off command in the script for it to function correctly, as the resume command is linked to the previous timeout used.
Stop DPMS while using applications

The above setup will result in your monitor powering off while you are doing things like playing a game, watching a video or listening to music where you might not touch the system for longer than the timeout period.

To fix this you can either use Hyprlands built in Window Rules V2 function which has a idleinhibit rule or you can install one of either idlehack-gitAUR or sway-audio-idle-inhibit-gitAUR. The former uses D-Bus to prevent Swayidle requests whenever Firefox or Chromium are playing audio/video. The latter prevents Swayidle requests whenever any application is playing audio.

For programs that use org.freedesktop.ScreenSaver.inhibit to pause the screensaver, you can install wscreensaver-bridge-gitAUR to implement it for Hyprland (or any Wayland compositor that support the idle-inhibit protocol).

Status bar

Hyprland requires a wayland-compatible external application to display a status bar. Using waybar as an example, we simply need to call it as follows:

~/.config/hypr/hyprland.conf
...
exec-once = waybar -c ~/.config/waybar/waybar.conf
...

Workspace overview

waybar has a built in, fully customisable module that supports Hyprland workspace switching natively.

See the waybar Wiki [1] for details.

Polkit authentication

Polkit authentication requires the use of an external authentication agent. Hyprland recommends using polkit-kde-agent but any should work.

Call it as follows:

~/.config/hypr/hyprland.conf
...
exec-once = /usr/lib/polkit-kde-authentication-agent-1
...

Desktop wallpaper

Hyprland requires a wayland-compatible external application to manage desktop wallpapers. Using swwwAUR as an example, we simply need to call it as follows:

~/.config/hypr/hyprland.conf
...
exec-once = swww init
exec-once = swww img path/to/image
...

Using a script to change wallpaper every X minutes

Create the following script and make sure its executable:

~/.config/hypr/scripts/swww-random
#!/bin/bash

# This script will randomly go through the files of a directory, setting it
# up as the wallpaper at regular intervals
#
# NOTE: this script uses bash (not POSIX shell) for the RANDOM variable

if [[ $# -lt 1 ]] || [[ ! -d $1   ]]; then
	echo "Usage:
	$0 <dir containing images>"
	exit 1
fi

# Edit below to control the images transition
export SWWW_TRANSITION_FPS=144
export SWWW_TRANSITION_STEP=2
export SWWW_TRANSITION_TYPE=random

# This controls (in seconds) when to switch to the next image
INTERVAL=300

while true; do
	find "$1" \
		| while read -r img; do
			echo "$((RANDOM % 1000)):$img"
		done \
		| sort -n | cut -d':' -f2- \
		| while read -r img; do
			swww img "$img"
			sleep $INTERVAL
		done
done

Next create a new folder to store background images, something like ~/.config/hypr/backgrounds should work fine, and populate it with any images you want.

Finally call the script:

~/.config/hypr/hyprland.conf
...
exec-once = swww init
exec-once = ~/.config/hypr/scripts/swww-random ~/.config/hypr/background
...

On screen notifications

On screen notifications for actions like brightness and volume changes are possible by using external notification daemons. This is a very complex topic and covering it completely is beyond the scope of this page. Rather, this section will focus on mako so go ahead and install it.

See Desktop notifications for further instructions and Desktop notifications#Standalone for a list of alternatives.

Note:
  • All scripts offered here are examples and will very likely need to be adjusted for your setup.
  • All scripts in this section must be executable.

Mako

This article or section needs language, wiki syntax or style improvements. See Help:Style for reference.

Reason: This section goes beyond the scope of this page and probably deserves its own dedicated page. (Discuss in Talk:Hyprland)

Mako is a lightweight notification daemon, you can read mako(5) for details. Its configuration file is ~/.config/mako/config, icons used for OSD are stored at ~/.config/mako/icons/ and should be in PNG format.

For the rest of this section all the images used by the scripts are available from this GitHub folder.

Keyboard backlight notifications

First create the following script:

~/.config/hypr/scripts/kbbacklight
#!/usr/bin/env bash

iDIR="$HOME/.config/mako/icons"

# Get brightness
get_backlight() {
	LIGHT="$(cat /sys/class/leds/*::kbd_backlight/brightness)"
	echo "${LIGHT}"
}

# Get icons
get_icon() {
	current="$(cat /sys/class/leds/*::kbd_backlight/brightness)"

	if [[ ("$current" -ge "0") && ("$current" -le "1") ]]; then
		icon="$iDIR/brightness-20.png"
	elif [[ ("$current" -ge "1") && ("$current" -le "2") ]]; then
		icon="$iDIR/brightness-60.png"
	elif [[ ("$current" -ge "2") && ("$current" -le "3") ]]; then
		icon="$iDIR/brightness-100.png"
	fi
}

# Notify
notify_user() {
	notify-send -h string:x-canonical-private-synchronous:sys-notify -u low -i "$icon" "Keyboard Brightness : $(brightnessctl -d '*::kbd_backlight' g)"
}

# Increase brightness
inc_backlight() {
	brightnessctl -d *::kbd_backlight set 33%+ && get_icon && notify_user
}

# Decrease brightness
dec_backlight() {
	brightnessctl -d *::kbd_backlight set 33%- && get_icon && notify_user
}

# Zero brightness
zero_backlight() {
	brightnessctl -d *::kbd_backlight s 0%
}

# Full brightness
full_backlight() {
	brightnessctl -d *::kbd_backlight s 100%
}

# Execute accordingly
if [[ "$1" == "--get" ]]; then
	brightnessctl -d '*::kbd_backlight' g
elif [[ "$1" == "--inc" ]]; then
	inc_backlight
elif [[ "$1" == "--dec" ]]; then
	dec_backlight
elif [[ "$1" == "--zero" ]]; then
	zero_backlight
elif [[ "$1" == "--full" ]]; then
	full_backlight

else
	get_backlight
fi

Then add the following (or edit any existing binds):

~/.config/hypr/hyprland.conf
# Keyboard brightness
bind = SUPER, F2, exec, ~/.config/hypr/scripts/kbbacklight --dec
bind = SUPER, F3, exec, ~/.config/hypr/scripts/kbbacklight --inc
Media key notifications

First create the following script:

~/.config/hypr/scripts/volume
#!/usr/bin/env bash

iDIR="$HOME/.config/mako/icons"

# Get Volume
get_volume() {
	volume=$(pamixer --get-volume)
	echo "$volume"
}

# Get icons
get_icon() {
	current=$(get_volume)
	if [[ "$current" -eq "0" ]]; then
		echo "$iDIR/volume-mute.png"
	elif [[ ("$current" -ge "0") && ("$current" -le "30") ]]; then
		echo "$iDIR/volume-low.png"
	elif [[ ("$current" -ge "30") && ("$current" -le "60") ]]; then
		echo "$iDIR/volume-mid.png"
	elif [[ ("$current" -ge "60") && ("$current" -le "100") ]]; then
		echo "$iDIR/volume-high.png"
	fi
}

# Notify
notify_user() {
	notify-send -h string:x-canonical-private-synchronous:sys-notify -u low -i "$(get_icon)" "Volume : $(get_volume) %"
}

# Increase Volume
inc_volume() {
	pamixer -i 5 && notify_user
}

# Decrease Volume
dec_volume() {
	pamixer -d 5 && notify_user
}

# Toggle Mute
toggle_mute() {
	if [ "$(pamixer --get-mute)" == "false" ]; then
		pamixer -m && notify-send -h string:x-canonical-private-synchronous:sys-notify -u low -i "$iDIR/volume-mute.png" "Volume Switched OFF"
	elif [ "$(pamixer --get-mute)" == "true" ]; then
		pamixer -u && notify-send -h string:x-canonical-private-synchronous:sys-notify -u low -i "$(get_icon)" "Volume Switched ON"
	fi
}

# Toggle Mic
toggle_mic() {
	if [ "$(pamixer --default-source --get-mute)" == "false" ]; then
		pamixer --default-source -m && notify-send -h string:x-canonical-private-synchronous:sys-notify -u low -i "$iDIR/microphone-mute.png" "Microphone Switched OFF"
	elif [ "$(pamixer --default-source --get-mute)" == "true" ]; then
		pamixer -u --default-source u && notify-send -h string:x-canonical-private-synchronous:sys-notify -u low -i "$iDIR/microphone.png" "Microphone Switched ON"
	fi
}
# Get icons
get_mic_icon() {
	current=$(pamixer --default-source --get-volume)
	if [[ "$current" -eq "0" ]]; then
		echo "$iDIR/microphone.png"
	elif [[ ("$current" -ge "0") && ("$current" -le "30") ]]; then
		echo "$iDIR/microphone.png"
	elif [[ ("$current" -ge "30") && ("$current" -le "60") ]]; then
		echo "$iDIR/microphone.png"
	elif [[ ("$current" -ge "60") && ("$current" -le "100") ]]; then
		echo "$iDIR/microphone.png"
	fi
}
# Notify
notify_mic_user() {
	notify-send -h string:x-canonical-private-synchronous:sys-notify -u low -i "$(get_mic_icon)" "Mic-Level : $(pamixer --default-source --get-volume) %"
}

# Increase MIC Volume
inc_mic_volume() {
	pamixer --default-source -i 5 && notify_mic_user
}

# Decrease MIC Volume
dec_mic_volume() {
	pamixer --default-source -d 5 && notify_mic_user
}

# Execute accordingly
if [[ "$1" == "--get" ]]; then
	get_volume
elif [[ "$1" == "--inc" ]]; then
	inc_volume
elif [[ "$1" == "--dec" ]]; then
	dec_volume
elif [[ "$1" == "--toggle" ]]; then
	toggle_mute
elif [[ "$1" == "--toggle-mic" ]]; then
	toggle_mic
elif [[ "$1" == "--get-icon" ]]; then
	get_icon
elif [[ "$1" == "--get-mic-icon" ]]; then
	get_mic_icon
elif [[ "$1" == "--mic-inc" ]]; then
	inc_mic_volume
elif [[ "$1" == "--mic-dec" ]]; then
	dec_mic_volume
else
	get_volume
fi

Then add the following (or edit any existing binds):

~/.config/hypr/hyprland.conf
# Volume
bind = , XF86AudioRaiseVolume, exec, ~/.config/hypr/scripts/volume --inc 
bind = , XF86AudioLowerVolume, exec, ~/.config/hypr/scripts/volume --dec 
bind = , XF86AudioMicMute, exec, ~/.config/hypr/scripts/volume --toggle-mic 
bind = , XF86AudioMute, exec, ~/.config/hypr/scripts/volume --toggle
Screen backlight notifications

First create the following script:

~/.config/hypr/scripts/backlight
!/usr/bin/env bash

iDIR="$HOME/.config/mako/icons"

# Get brightness
get_backlight() {
	LIGHT=$(printf "%.0f\n" $(brightnessctl g))
	echo "${LIGHT}"
}

# Get icons
get_icon() {
	current="$(get_backlight)"
	if [[ ("$current" -ge "0") && ("$current" -le "19200") ]]; then
		icon="$iDIR/brightness-20.png"
	elif [[ ("$current" -ge "19200") && ("$current" -le "38400") ]]; then
		icon="$iDIR/brightness-40.png"
	elif [[ ("$current" -ge "38400") && ("$current" -le "57600") ]]; then
		icon="$iDIR/brightness-60.png"
	elif [[ ("$current" -ge "57600") && ("$current" -le "76800") ]]; then
		icon="$iDIR/brightness-80.png"
	elif [[ ("$current" -ge "76800") && ("$current" -le "96000") ]]; then
		icon="$iDIR/brightness-100.png"
	fi
}

# Notify
notify_user() {
	notify-send -h string:x-canonical-private-synchronous:sys-notify -u low -i "$icon" "Brightness : $(get_backlight)"
}

# Increase brightness
inc_backlight() {
	brightnessctl s +5% && get_icon && notify_user
}

# Decrease brightness
dec_backlight() {
	brightnessctl s 5%- && get_icon && notify_user
}

# Execute accordingly
if [[ "$1" == "--get" ]]; then
	get_backlight
elif [[ "$1" == "--inc" ]]; then
	inc_backlight
elif [[ "$1" == "--dec" ]]; then
	dec_backlight
else
	get_backlight
fi

Then add the following (or edit any existing binds):

~/.config/hypr/hyprland.conf
# Screen brightness
bind = , XF86MonBrightnessUp, exec, ~/.config/hypr/scripts/backlight --inc 
bind = , XF86MonBrightnessDown, exec, ~/.config/hypr/scripts/backlight --dec
Keyboard language notifications

To run this script, you need a command-line JSON processor gojqAUR.

First create the following script:

~/.config/hypr/scripts/lang
#!/usr/bin/env bash

icon="$HOME/.config/mako/icons/language.png"

# Get language
get_lang() {
	lang=$(hyprctl devices -j | gojq -r '.keyboards[] | select(.name == "at-translated-set-2-keyboard") | .active_keymap' | cut -c 1-2 | tr 'A-Z' 'a-z')
	case $lang in
		en)
			lang="English language"
			;;
		ru)
			lang="Русский язык"
			;;
		uk)
			lang="Українська мова"
			;;
	esac
	echo $lang
}

# Notify
notify-send -h string:x-canonical-private-synchronous:sys-notify -u low -i "$icon" "$(get_lang)"

Then add the following (or edit any existing binds):

~/.config/hypr/hyprland.conf
device:at-translated-set-2-keyboard {
    kb_layout = us,ru,ua
    kb_variant = lang
    kb_options = grp:win_space_toggle
}

# Language
bind = SUPER, SPACE, exec, ~/.config/hypr/scripts/lang

Power control

Hyprland requires a wayland-compatible external application for power control. Using nwg-barAUR as an example, we simply need to bind it as follows:

~/.config/hypr/hyprland.conf
...
bind = SUPER, ESCAPE, exec, nwg-bar
...

Clipboard

Wayland clipboard behaviour deletes data when closing the application we copied it from. Other desktop environments work around this by using dedicated clipboard managers and on Hyprland there are multiple compatible choices. See the upstream Wiki for more information.

This section will cover cliphist as it supports copying images as well as text, start by adding the following:

~/.config/hypr/hyprland.conf
...
exec-once = wl-paste --type text --watch cliphist store 
exec-once = wl-paste --type image --watch cliphist store
...

Then create a bind to call the history in your chosen application launcher:

~/.config/hypr/hyprland.conf
...
bind = SUPER, V, exec, cliphist list | wofi --dmenu | cliphist decode | wl-copy
...

Now pressing Super+v will open up a wofi window with a clipboard history list.

Enable/disable devices

To enable/disable devices (e.g. touchpad), first use

$ hyprctl devices

to get the name of your device.

Put these lines of code into your configuration file (replace <device_name> with the name of your device queried above) to turn the device on/off:

~/.config/hypr/hyprland.conf
device:<device_name> {
  enabled = {true/false}
}

To dynamically switch the device on/off use hyprctl:

$ hyprctl keyword "device:<device_name>:enabled" {true|false}

You can also create a keybinding, e.g.:

~/.config/hypr/hyprland.conf
...
bind = $mainMod, t, exec, hyprctl keyword "device:pixa3854:00-093a:0274-touchpad:enabled" false
bind = $mainMod Shift, t, exec, hyprctl keyword "device:pixa3854:00-093a:0274-touchpad:enabled" true
...

Troubleshooting

xdg-desktop-portal-hyprland is using a lot of CPU

This is a known bug [2] that should be resolved in the latest Git build. You can work around it by calling the nuclear script from the Hyprland wiki, as outlined here, in your hyprland.conf file.

See also