Personal Hyprland Configuration with Waybar
- Welcome
- Hyprland
- Waybar
Welcome
My personal configuration of Hyprland, written as an Org Mode document.
Run the block below with C-c C-c
to tangle code blocks to config file.
(org-mode-restart)
(org-babel-tangle)
Hyprland
Monitors
monitor = desc:LG Display 0x0625, disable
monitor = desc:LG Electronics LG ULTRAGEAR 305MXUN80518, 2560x1440@144, 0x0, 1
monitor = desc:LG Electronics LG ULTRAGEAR 112NTTQC0153, 2560x1440@165, 2560x0, 1
monitor = desc:LG Electronics LG ULTRAGEAR 111NTUWM4574, 2560x1440@165, 5120x0, 1
monitor = , preferred, auto, 1
Variables
$terminal = foot
$fileManager = thunar
$menu = rofi -show combi -run-command "uwsm app -- {cmd}"
Autostart
Autostart necessary processes (like notifications daemons, status bars, etc.) Or execute your favorite apps at launch like this:
exec-once = $terminal exec-once = nm-applet & exec-once = waybar & hyprpaper & firefox
If using uwsm
, prefix application startup commands with uwsm app --
:
exec-once = uwsm app -- mycommand --arg1 --arg2 bind = SUPER, E, exec, uwsm app -- pcmanfm-qt.desktop
exec-once = uwsm app -- waybar --config $HOME/.config/hypr/waybar/config.jsonc --style $HOME/.config/dwl/waybar/style.css
Environment Variables
uwsm
users should avoid placing environment variables here. Instead, use ~/.config/uwsm/env
for theming, xcursor, nvidia and toolkit variables, and ~.config/uwsm/env-hyprland
for HYPR*
and AQ_*
variables. The format is export KEY=VAL
.
export XCURSOR_SIZE=24
See uwsm readme for additional information.
Permissions
ecosystem { enforce_permissions = 1 } permission = /usr/(bin|local/bin)/grim, screencopy, allow permission = /usr/(lib|libexec|lib64)/xdg-desktop-portal-hyprland, screencopy, allow
Look and Feel
General
general {
gaps_in = 5
gaps_out = 20
border_size = 2
# https://wiki.hyprland.org/Configuring/Variables/#variable-types for info about colors
col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
col.inactive_border = rgba(595959aa)
# Set to true enable resizing windows by clicking and dragging on borders and gaps
resize_on_border = false
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
allow_tearing = false
layout = dwindle
}
Decoration
decoration {
rounding = 10
rounding_power = 2
# Change transparency of focused and unfocused windows
active_opacity = 1.0
inactive_opacity = 1.0
shadow {
enabled = true
range = 4
render_power = 3
color = rgba(1a1a1aee)
}
blur {
enabled = true
size = 3
passes = 1
vibrancy = 0.1696
}
}
Animations
animations {
enabled = true
bezier = easeOutQuint,0.23,1,0.32,1
bezier = easeInOutCubic,0.65,0.05,0.36,1
bezier = linear,0,0,1,1
bezier = almostLinear,0.5,0.5,0.75,1.0
bezier = quick,0.15,0,0.1,1
animation = global, 1, 10, default
animation = border, 1, 5.39, easeOutQuint
animation = windows, 1, 4.79, easeOutQuint
animation = windowsIn, 1, 4.1, easeOutQuint, popin 87%
animation = windowsOut, 1, 1.49, linear, popin 87%
animation = fadeIn, 1, 1.73, almostLinear
animation = fadeOut, 1, 1.46, almostLinear
animation = fade, 1, 3.03, quick
animation = layers, 1, 3.81, easeOutQuint
animation = layersIn, 1, 4, easeOutQuint, fade
animation = layersOut, 1, 1.5, linear, fade
animation = fadeLayersIn, 1, 1.79, almostLinear
animation = fadeLayersOut, 1, 1.39, almostLinear
animation = workspaces, 1, 1.94, almostLinear, fade
animation = workspacesIn, 1, 1.21, almostLinear, fade
animation = workspacesOut, 1, 1.94, almostLinear, fade
}
Dwindle Layout
dwindle {
pseudotile = true # Master switch for pseudotiling. See keybinding section to enable
preserve_split = true # You probably want this
}
Master Layout
master {
new_status = master
}
Miscellaneous
misc {
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :(
}
Input
Keyboard and Mouse
input {
kb_layout = us
kb_variant =
kb_model =
kb_options =
kb_rules =
follow_mouse = 1
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
touchpad {
natural_scroll = true
}
}
Gestures
gestures {
workspace_swipe = true
}
Device
device { name = epic-mouse-v1 sensitivity = -0.5 }
Keybindings
bind = MODS, key, dispatcher, params
Mod Key
$mainMod = SUPER # Sets "Windows" key as main modifier
Session Control
bind = $mainMod SHIFT, Q, exec, loginctl terminate-user ""
Launch Programs
bind = $mainMod SHIFT, Return, exec, uwsm app -- $terminal
bind = $mainMod, E, exec, uwsm app -- $fileManager
bind = $mainMod, P, exec, uwsm app -- $menu
Control Windows / Layout
bind = $mainMod SHIFT, C, killactive
bind = $mainMod SHIFT, F, fullscreen
bind = $mainMod, F, togglefloating
bind = $mainMod, D, pseudo # dwindle
bind = $mainMod, S, togglesplit # dwindle
Move Focus
Move focus with mainMod + vim keys
bind = $mainMod, H, movefocus, l
bind = $mainMod, L, movefocus, r
bind = $mainMod, K, movefocus, u
bind = $mainMod, J, movefocus, d
Switch Workspaces
Switch workspaces with mainMod + [0-9]
bind = $mainMod, 1, workspace, 1
bind = $mainMod, 2, workspace, 2
bind = $mainMod, 3, workspace, 3
bind = $mainMod, 4, workspace, 4
bind = $mainMod, 5, workspace, 5
bind = $mainMod, 6, workspace, 6
bind = $mainMod, 7, workspace, 7
bind = $mainMod, 8, workspace, 8
bind = $mainMod, 9, workspace, 9
bind = $mainMod, 0, workspace, 10
Move Windows to Workspace
Move active window to a workspace with mainMod + SHIFT + [0-9]
bind = $mainMod SHIFT, 1, movetoworkspace, 1
bind = $mainMod SHIFT, 2, movetoworkspace, 2
bind = $mainMod SHIFT, 3, movetoworkspace, 3
bind = $mainMod SHIFT, 4, movetoworkspace, 4
bind = $mainMod SHIFT, 5, movetoworkspace, 5
bind = $mainMod SHIFT, 6, movetoworkspace, 6
bind = $mainMod SHIFT, 7, movetoworkspace, 7
bind = $mainMod SHIFT, 8, movetoworkspace, 8
bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10
Special Workspace
Example special workspace (scratchpad)
bind = $mainMod, S, togglespecialworkspace, magic bind = $mainMod SHIFT, S, movetoworkspace, special:magic
Workspace Scroll
Scroll through existing workspaces with mainMod + scroll
bind = $mainMod, mouse_down, workspace, e+1
bind = $mainMod, mouse_up, workspace, e-1
Move / Resize Windows
Move/resize windows with mainMod + LMB/RMB and dragging
bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow
Laptop Multimedia Keys
Laptop multimedia keys for volume and LCD brightness
bindel = , XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+
bindel = , XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
bindel = , XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
bindel = , XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
bindel = , XF86MonBrightnessUp, exec, brightnessctl s 10%+
bindel = , XF86MonBrightnessDown, exec, brightnessctl s 10%-
Media Controls
Requires playerctl
bindl = , XF86AudioNext, exec, playerctl next
bindl = , XF86AudioPause, exec, playerctl play-pause
bindl = , XF86AudioPlay, exec, playerctl play-pause
bindl = , XF86AudioPrev, exec, playerctl previous
Windows and Workspaces
Window Rules
Example windowrule
windowrule = float,class:^(kitty)$,title:^(kitty)$
Ignore maximize requests from apps. You'll probably like this.
windowrule = suppressevent maximize, class:.*
Fix some dragging issues with XWayland
windowrule = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
Smart Gaps
workspace = w[tv1], gapsout:0, gapsin:0
workspace = f[1], gapsout:0, gapsin:0
windowrule = bordersize 0, floating:0, onworkspace:w[tv1]
windowrule = rounding 0, floating:0, onworkspace:w[tv1]
windowrule = bordersize 0, floating:0, onworkspace:f[1]
windowrule = rounding 0, floating:0, onworkspace:f[1]
Waybar
Start Configuration
// -*- mode: jsonc -*-
{
Bar
Configuration
"layer": "top", // Waybar at top layer
// "output": "",
"position": "top", // Waybar position (top|bottom|left|right)
// "height": 25, // Waybar height (to be removed for auto height)
// "width": 1280, // Waybar width
"spacing": 4, // Gaps between modules (4px)
"mode": "dock",
"start_hidden": false,
"fixed-center": true,
"reload_style_on_change": true,
"modules-left": [
"group/power-menu",
"dwl/tags",
"dwl/window#title",
"dwl/window#layout",
],
"modules-center": [
"tray",
],
"modules-right": [
"group/media-playing",
"pulseaudio",
"idle_inhibitor",
"custom/system76-power",
"cpu",
"memory",
"disk",
"battery",
"clock",
"group/dunst",
],
"group/power-menu": {
"orientation": "inherit",
"modules": [
"custom/power-menu-launcher",
"custom/power-menu-shutdown",
"custom/power-menu-reboot",
"custom/power-menu-sleep",
"custom/power-menu-lock",
"custom/power-menu-logout",
],
"drawer": {
"transition-duration": 500,
"transition-left-to-right": true,
"click-to-reveal": false,
},
},
"group/media-playing": {
"orientation": "inherit",
"modules": [
"custom/media-playing-source",
"custom/media-playing-prev",
"custom/media-playing-play-pause",
"custom/media-playing-next",
],
},
"group/dunst": {
"orientation": "inherit",
"modules": [
"custom/dunst-status",
"custom/dunst-history-view",
"custom/dunst-clear",
"custom/dunst-history-clear",
],
"drawer": {
"transition-duration": 500,
"transition-left-to-right": true,
"click-to-reveal": false,
},
},
Styling
window#waybar {
background: transparent;
}
#window {
padding: 0px 0px;
color: transparent;
background: transparent;
}
widget {
background: #282a36;
border-radius: 25px;
}
label.module {
padding: 0px 10px;
}
button {
border-radius: 0px;
padding: 0px 0px;
}
.module,button {
font-size: 15px;
font-family: Ubuntu Nerd Font;
}
Modules
Battery
Configuration
"battery": {
"interval": 60,
"format": "{icon} {capacity}%",
"format-icons": ["", "", "", "", "", "", "", "", "", "", ""],
"tooltip": true,
"tooltip-format": "\t{timeTo}\n\t{power} W\n\t{cycles}\n\t{health}%",
},
Styling
#battery {
background: transparent;
color: #ff79c6;
}
CPU
Configuration
"cpu": {
"interval": 5,
"format": " {usage}%",
"tooltip": true,
"on-click-right": "foot btop",
},
Styling
#cpu {
background: transparent;
color: #ffb86c;
}
Clock
Configuration
"clock": {
"interval": 60,
"format": " {:%I:%M %p}",
"tooltip": true,
"tooltip-format": "<tt><small>{calendar}</small></tt>",
"calendar": {
"mode" : "month",
"mode-mon-col" : 3,
"weeks-pos" : "left",
"on-scroll" : 1,
"format": {
"months": "<span color='#50fa7b'><b>{}</b></span>",
"days": "<span color='#f8f8f2'><b>{}</b></span>",
"weeks": "<span color='#8be9fd'><b>W{}</b></span>",
"weekdays": "<span color='#f1fa8c'><b>{}</b></span>",
"today": "<span color='#bd93f9'><b><u>{}</u></b></span>"
},
},
"actions": {
"on-click": "mode",
"on-click-right": "shift_reset",
"on-scroll-up": "shift_up",
"on-scroll-down": "shift_down",
},
},
Styling
#clock {
background: transparent;
color: #bd93f9;
}
Dunst
Configuration
"custom/dunst-status": {
"exec": "~/.config/dwl/waybar/scripts/dunst.sh",
"restart-interval": 1,
"on-click": "~/.scripts/dunst.sh --dnd",
"on-click-right": "~/.scripts/dunst.sh --rofi",
"tooltip": true,
"tooltip-format": "Toggle Do Not Disturb",
},
"custom/dunst-clear": {
"format": "",
"on-click": "~/.scripts/dunst.sh --close-all",
"tooltip": true,
"tooltip-format": "Close Open Notifications",
},
"custom/dunst-history-view": {
"format": "",
"on-click": "~/.scripts/dunst.sh --history",
"tooltip": true,
"tooltip-format": "View Notification History",
},
"custom/dunst-history-clear": {
"format": "",
"on-click": "~/.scripts/dunst.sh --history-clear",
"tooltip": true,
"tooltip-format": "Clear Notification History",
},
Styling
box#dunst {
padding: 0px 10px;
}
#custom-dunst-status {
background: transparent;
color: #50fa7b;
padding: 0px 5px;
}
#custom-dunst-clear {
background: transparent;
color: #50fa7b;
padding: 0px 5px;
}
#custom-dunst-history-view {
background: transparent;
color: #50fa7b;
padding: 0px 5px;
}
#custom-dunst-history-clear {
background: transparent;
color: #50fa7b;
padding: 0px 5px;
}
Script
isPaused=$(dunstctl is-paused)
notificationCount=$(dunstctl count history)
if [[ "$isPaused" == "true" ]]; then
echo " $notificationCount"
else
echo " $notificationCount"
fi
DWL
Configuration
"dwl/tags": {
"num-tags": 9,
"tag-labels": [ " ₁", " ₂", " ₃", " ₄", " ₅", " ₆", " ₇", " ₈", " ₉" ],
"disable-click": false
},
"dwl/window#title": {
"format": "{title}",
"all-outputs": false,
"icon": true,
"icon-size": 21,
"tooltip": true,
"max-length": 30,
},
"dwl/window#layout": {
"format": "{layout}",
"tooltip": false,
"all-outputs": false,
"icon": false,
},
Styling
#tags {
padding: 0px 10px;
}
#tags button {
background: transparent;
color: #44475a;
padding: 0px 5px;
}
#tags button.occupied {
background: transparent;
color: #f1fa8c;
}
#tags button.focused {
background: transparent;
box-shadow: inset 0 -3px #bd93f9;
}
#tags button.urgent {
background: transparent;
color: #ff5555;
}
#window.title {
background: transparent;
color: #f8f8f2;
padding: 0px 10px;
}
#window.layout {
background: transparent;
color: #50fa7b;
padding: 0px 10px;
}
Disk
Configuration
"disk": {
"interval": 60,
"format": " {percentage_used}%",
"tooltip": true,
"tooltip-format": "Used: {used} ({percentage_used}%)\nFree: {free} ({percentage_free}%)\nTotal: {total}",
"on-click-right": "qdirstat",
},
Styling
#disk {
background: transparent;
color: #f1fa8c;
}
Idle Inhibitor
Configuration
"idle_inhibitor": {
"format": "{icon}",
"format-icons": {
"activated": " on",
"deactivated": " off",
},
"tooltip": true,
"tooltip-format-activated": "Idle Inhibitor: {status}",
"tooltip-format-deactivated": "Idle Inhibitor: {status}",
"start-activated": true,
},
Styling
#idle_inhibitor.activated {
background: transparent;
color: #f1fa8c;
}
#idle_inhibitor.deactivated {
background: transparent;
color: #44475a;
}
Memory
Configuration
"memory": {
"interval": 5,
"format": " {percentage}%",
"tooltip": true,
"tooltip-format": "RAM:\n\tUsed: {used} GiB ({percentage}%)\n\tFree: {avail} GiB\n\tTotal: {total} GiB\nSwap:\n\tUsed: {swapUsed} GiB ({swapPercentage}%)\n\tFree: {swapAvail} GiB\n\tTotal: {swapTotal} GiB",
"on-click-right": "foot btop",
},
Styling
#memory {
background: transparent;
color: #8be9fd;
}
Playerctl
Configuration
"custom/media-playing-source": {
"exec": "~/.config/dwl/waybar/scripts/get-media-playing.sh",
"return-type": "json",
"restart-interval": 1,
"on-click": "~/.scripts/playerctl.sh --change",
"tooltip": true,
},
"custom/media-playing-prev": {
"format": "",
"on-click": "~/.scripts/playerctl.sh --prev",
"tooltip": false,
},
"custom/media-playing-play-pause": {
"exec": "~/.config/dwl/waybar/scripts/get-media-status-icon.sh",
"restart-interval": 1,
"on-click": "~/.scripts/playerctl.sh --play-pause",
"tooltip": false,
},
"custom/media-playing-next": {
"format": "",
"on-click": "~/.scripts/playerctl.sh --next",
"tooltip": false,
},
Styling
box#media-playing {
padding: 0px 10px;
}
#custom-media-playing-source {
background: transparent;
color: #ff5555;
padding: 0px 5px;
}
#custom-media-playing-prev {
background: transparent;
color: #ff5555;
padding: 0px 5px;
}
#custom-media-playing-play-pause {
background: transparent;
color: #ff5555;
padding: 0px 5px;
}
#custom-media-playing-next {
background: transparent;
color: #ff5555;
padding: 0px 5px;
}
Script
mediaStatus=$(playerctl --player=playerctld metadata 2>&1)
if [[ "$mediaStatus" == "No player could handle this command" ]]; then
echo ""
else
trackid=$(playerctl --player=playerctld metadata --format '{{ mpris:trackid }}')
title=$(playerctl --player=playerctld metadata --format '{{ xesam:title }}')
if grep -q -i "netflix" <<< "$title"; then
echo ""
elif grep -q -i "hulu" <<< "$title"; then
echo ""
elif grep -q -i "prime video" <<< "$title"; then
echo ""
elif grep -q -i "youtube tv" <<< "$title"; then
echo ""
elif grep -q -i "chromium" <<< "$trackid"; then
echo ""
elif grep -q -i "vlc" <<< "$trackid"; then
echo ""
elif grep -q -i "spotify" <<< "$trackid"; then
echo ""
else
echo ""
fi
fi
mediaStatus=$(`dirname $0`/get-media-status.sh)
if [[ "$mediaStatus" == "N/A" ]]; then
echo ""
else
if [[ "$mediaStatus" == "Playing" ]]; then
echo ""
elif [[ "$mediaStatus" == "Paused" ]]; then
echo ""
fi
fi
mediaStatus=$(playerctl --player=playerctld metadata 2>&1)
if [[ "$mediaStatus" == "No player could handle this command" ]]; then
echo "N/A"
else
status=$(playerctl --player=playerctld metadata --format '{{ status }}')
echo $status
fi
mediaSourceIcon=$(`dirname $0`/get-media-source-icon.sh)
mediaStatus=$(playerctl --player=playerctld metadata 2>&1)
if [[ "$mediaStatus" == "No player could handle this command" ]]; then
artist="N/A"
title="N/A"
album="N/A"
status="N/A"
else
artist=$(playerctl --player=playerctld metadata --format '{{ xesam:artist }}')
title=$(playerctl --player=playerctld metadata --format '{{ xesam:title }}')
album=$(playerctl --player=playerctld metadata --format '{{ xesam:album }}')
status=$(playerctl --player=playerctld metadata --format '{{ status }}')
if [[ $artist == "" ]]; then
artist="N/A"
fi
if [[ $title == "" ]]; then
title="N/A"
fi
if [[ $album == "" ]]; then
album="N/A"
fi
if [[ $status == "" ]]; then
status="N/A"
fi
fi
echo '{"text":"'$mediaSourceIcon'","tooltip":"\t'${title//'"'/'\"'}'\r\t'${artist//'"'/'\"'}'\r\t'${album//'"'/'\"'}'\r\t'${status//'"'/'\"'}'"}'
Power Menu
Configuration
"custom/power-menu-launcher": {
"format": "",
"on-click": "rofi -show combi",
"on-click-right": "~/.scripts/control-center.sh --rofi",
"tooltip": true,
"tooltip-format": "Application Launcher",
},
"custom/power-menu-shutdown": {
"format": "",
"on-click": "~/.scripts/session.sh --shutdown",
"tooltip": true,
"tooltip-format": "Shutdown",
},
"custom/power-menu-reboot": {
"format": "",
"on-click": "~/.scripts/session.sh --reboot",
"tooltip": true,
"tooltip-format": "Reboot",
},
"custom/power-menu-sleep": {
"format": "⏾",
"on-click": "~/.scripts/session.sh --sleep",
"tooltip": true,
"tooltip-format": "Sleep",
},
"custom/power-menu-lock": {
"format": "",
"on-click": "~/.scripts/session.sh --lock",
"tooltip": true,
"tooltip-format": "Lock",
},
"custom/power-menu-logout": {
"format": "",
"on-click": "~/.scripts/session.sh --logout",
"tooltip": true,
"tooltip-format": "Logout",
},
Styling
box#power-menu {
padding: 0px 10px;
}
#custom-power-menu-launcher {
background: transparent;
color: #8be9fd;
padding: 0px 5px;
}
#custom-power-menu-shutdown {
background: transparent;
color: #ff5555;
padding: 0px 5px;
}
#custom-power-menu-reboot {
background: transparent;
color: #50fa7b;
padding: 0px 5px;
}
#custom-power-menu-sleep {
background: transparent;
color: #f1fa8c;
padding: 0px 5px;
}
#custom-power-menu-lock {
background: transparent;
color: #ff79c6;
padding: 0px 5px;
}
#custom-power-menu-logout {
background: transparent;
color: #ffb86c;
padding: 0px 5px;
}
Pulseaudio
Configuration
"pulseaudio": {
"interval": 5,
"format": "{icon} {volume}%",
"format-bluetooth": "{icon} {volume}%",
"format-muted": " muted",
"format-icons": {
"hdmi": "",
"headset": "",
"speaker": "",
"headphone": "",
"car": "",
"hifi": "",
"default": "",
},
"scroll-step": 5,
"on-click": "~/.scripts/pactl.sh --mute",
"on-click-right": "~/.scripts/pactl.sh --mixer",
"tooltip": true,
"tooltip-format": "{desc}",
"scroll-step": 0.25,
},
Styling
#pulseaudio {
background: transparent;
color: #ff79c6;
}
System76 Power
Configuration
"custom/system76-power": {
"exec": "~/.config/dwl/waybar/scripts/system76-power.sh",
"return-type": "json",
"restart-interval": 60,
"on-click-right": "~/.scripts/cpu-gpu.sh --rofi",
"tooltip": true,
},
Styling
#custom-system76-power {
background: transparent;
color: #50fa7b;
}
Script
profile="$(sudo system76-power profile | sed -z '$ s/\n$//' | tr '\n' '\r')"
graphics="$(sudo system76-power graphics)"
graphicsPower="$(sudo system76-power graphics power)"
chargeThresholds="$(sudo system76-power charge-thresholds | sed -z '$ s/\n$//' | tr '\n' '\r')"
echo '{"text":" '$graphics'","tooltip":"\t'$graphics'\r\t'$graphicsPower'\r\r Profile\r'$profile'\r\r Charge Thresholds\r'$chargeThresholds'"}'
Tray
Configuration
"tray": {
"icon-size": 21,
"show-passive-items": true,
"spacing": 4,
"reverse-direction": false,
},
Styling
#tray {
background: transparent;
padding: 0px 10px;
}
End Configuration
}