This is my hyprland literate configuration.
Codes from hyprland.conf, pyprland.json, etc are generated from this org file,
by running M-x org-babel-tangle
inside emacs.
You may see comments like this in hyprland.conf, if you do not use emacs org mode, just ignore them, they are used by M-x org-babel-detangle
in emacs.
# [[file:hyprland.org::*Input][Input:1]]
# Input:1 ends here
Variables are “options” of hyprland. Each variable has a unique value assigned to it. Basically, variables controls how your hyprland desktop looks like. It also controls devices (not including monitors)
General options, controling window borders (size, color, etc) and more.
general {
gaps_in = 10
gaps_out = 20
gaps_workspaces = 30
border_size = 1
# col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
col.active_border = rgb(00F5F6)
col.inactive_border = rgba(24283be6)
layout = dwindle
# layout = master
}
Configureing window decorations, including opacity, border rounding, shadow, etc.
decoration {
active_opacity=1.0
fullscreen_opacity=1.0
rounding = 5 # border radius
drop_shadow = true
shadow_range = 15
shadow_render_power = 3
col.shadow = rgba(00F5F688)
blurls = nil
blur {
# enable kawase window background blur. default true
enabled = false
# blur size (distance). default 8
size = 5
# the amount of passes to perform. default 1
passes = 1
# make the blur layer ignore the opacity of the window.
# default false
ignore_opacity = false
# whether to enable further optimizations to the blur.
# massively improve performance. default true
new_optimizations = true
# make floating windows ignore tiled windows in their blur.
# Only available if blur_new_optimizations is true.
# Will reduce overhead on loating blur significantly.
xray = false
# how much noise to apply. 0.0 - 1.0. default 0.0117
noise = 0.0117
# contrast modulation for blur. 0.0 - 2.0. default 0.8916
contrast = 0.8916
# brightness modulation for blur. 0.0 - 2.0. default 0.8172
brightness = 0.8172
}
}
See https://wiki.hyprland.org/Configuring/Animations/ for more
animations {
enabled = true
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
animation = windows, 1, 3, default
animation = windowsOut, 1, 4, default, popin 50%
animation = border, 1, 5, default
animation = borderangle, 1, 5, default
animation = fade, 1, 5, default
animation = workspaces, 1, 6, default, slidevert
animation = specialWorkspace, 1, 5, default, slidefadevert
# animation = layersIn, 0
# animation = layersOut, 0
# animation = specialWorkspace, 1, 3, default, fade
}
Keyboard, mouse and touch pad input settings.
input {
kb_layout = us
kb_variant =
kb_model =
kb_options = caps:escape,shift:both_capslock
# kb_options =
kb_rules =
# kb_file = ~/.config/xkb/us-emacs.xkb
follow_mouse = 1
touchpad {
natural_scroll = true
}
sensitivity = 0.1 # -1.0 - 1.0, 0 means no modification.
repeat_rate = 30 # default 25
repeat_delay = 250 # default 600, I prefer faster entering repeat mode
}
Configuring how the windows are arranged when multiple window are tiled together in one workspace. Note that the variable general.layout controls the global layout. You can alse set workspace rules to control per workspace layout.
dwindle {
pseudotile = true
# master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
preserve_split = true # you probably want this
special_scale_factor = 0.85
}
master {
new_is_master = true
}
Configuring touchpad actions. See https://wiki.hyprland.org/Configuring/Variables/ for more
gestures {
workspace_swipe = true
workspace_swipe_fingers = 4
workspace_swipe_distance = 300
workspace_swipe_cancel_ratio = 0.5
workspace_swipe_min_speed_to_force = 10
workspace_swipe_create_new = true
}
group {
col.border_active = rgba(33ccffee) rgba(00ff99ee) 45deg
col.border_inactive = rgba(24283be6)
col.border_locked_active = rgba(33ccffee) rgba(00ff99ee) 45deg
col.border_locked_inactive = rgba(24283be6)
groupbar {
gradients = true
render_titles = true
font_size = 14
col.active = rgba(00ff99ee) rgba(33ccffee) 45deg
col.inactive = rgba(24283be6)
col.locked_active = rgba(00ff99ee) rgba(33ccffee) 45deg
col.locked_inactive = rgba(24283be6)
}
}
cursor {
no_warps = true
}
misc {
disable_hyprland_logo = true
disable_splash_rendering = true
vrr = 2
}
exec-once=kanshi
monitor=eDP-1, [email protected], 0x0, 1
Execute a shell script on startup of the compositor or on each time it’s reloaded.
exec-once=command
- will execute only on launch
exec=command
- will execute on each reload
exec-once = lxqt-policykit-agent
exec-once = swaync
exec-once = fcitx5 -d
# exec-once = pulseaudio -D
exec-once = clash-verge
exec-once = wl-paste --type text --watch cliphist store #Stores only text data
exec-once = wl-paste --type image --watch cliphist store #Stores only image data
exec-once = ags -b hypr -q; ags -b hypr -c ~/.config/hypr/ags/config.js
exec-once = hyprpaper;
For keybindings, there’re something worth considering:
- Move focus: to workspace, to monitor, to a direction
- Move window: to workspace, to monitor, to a direction
- Window functions: fullscreen, close, etc
- Window group: toggle group, lock group, move window into/outof group, etc
- Special workspace: toggle, move window into
- Exec: launch something or some commands
After spending an extensive amount of time configuring my dear hyprland, I learned out that it’s better to put relevant keybindings together than to put relevant functions/dispatchers together.
# helpful variables
$activeMonitorId="$(hyprctl -j monitors | jq -r '.[] | select(.focused == true) | .id')"
$activeWorkspaceId="$(hyprctl -j activeworkspace | jq -r '.id')"
$focusWorkspace="hyprctl dispatch workspace"
$focusMonitor="hyprctl dispatch focusmonitor"
$move2Workspace="hyprctl dispatch movetoworkspace"
$specialWorkspaceId="$(hyprctl -j activewindow | jq -r '.workspace.name' | cut -d':' -f2)"
$toggleOverview=
$mainMod = SUPER
# applications
bind = $mainMod, Return, exec, kitty --single-instance
bind = $mainMod, E, exec, thunar
bind = $mainMod, B, exec, vivaldi
bind = $mainMod, N, exec, neovide
bind = $mainMod, M, exec, emacs
# no longer use rofi to launch apps, but ags's internal launcher
# bind = $mainMod, R, exec, ~/.config/rofi/launcher.sh
bind = $mainMod, R, exec, anyrun
bind = $mainMod, F, exec, ~/.config/rofi/file.sh
bind = $mainMod, V, exec, ~/.config/rofi/clipboard.sh
# grimblast for screenshots
bind=,Print,execr, grimblast --notify --cursor copysave area ~/Pictures/$(date +'%Y-%m-%d_%H-%M-%S_1.png')
bind=SUPER,Print,exec,grimblast --notify save output ~/Pictures/$(date +'%Y-%m-%d_%H-%M-%S_1.png')
bind=SUPER SHIFT,Print,exec,grimblast --notify copy area - | swappy -f -
bind = $mainMod, Delete, exec, wlogout
bind = $mainMod CTRL ALT, Delete, exec, kill
bindle = , XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%+
bindle = , XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%-
bindle = , XF86MonBrightnessUp, exec, brightnessctl set 1%+ -q
bindle = , XF86MonBrightnessDown, exec, brightnessctl set 1%- -q
bindl = , XF86AudioStop, exec, playerctl stop
bindl = , XF86AudioPause, exec, playerctl pause
bindl = , XF86AudioPrev, exec, playerctl previous
bindl = , XF86AudioNext, exec, playerctl next
bindl = , XF86AudioPlay, exec, playerctl play-pause
#function
bind = $mainMod , Q, killactive,
bind = $mainMod , S, togglesplit, # dwindle
bind = $mainMod Alt, G, togglegroup,
bind = $mainMod , G, changegroupactive
bind = $mainMod , P, pin
# bind = $mainMod , O, execr, ~/.config/hypr/bin/eww_toggle_overview.sh
bind = $mainMod ALT, F9, pseudo, # dwindle
bind = $mainMod ALT, F10, togglefloating,
bind = $mainMod ALT, F11, fullscreen, 0
My directional keybindings is very wierd. It’s not HJKL, not wasd, not IJKL, not JKL;, BUT JLK; Therefore do not try to copy my keybindings below, you’ll definitely regret it
bind = $mainMod, left, movefocus, l
bind = $mainMod, right, movefocus, r
bind = $mainMod, up, movefocus, u
bind = $mainMod, down, movefocus, d
bind = $mainMod, J, movefocus, l
bind = $mainMod, L, movefocus, d
bind = $mainMod, K, movefocus, u
bind = $mainMod, semicolon, movefocus, r
bind = $mainMod SHIFT, left, movewindoworgroup, l
bind = $mainMod SHIFT, right, movewindoworgroup, r
bind = $mainMod SHIFT, up, movewindoworgroup, u
bind = $mainMod SHIFT, down, movewindoworgroup, d
bind = $mainMod SHIFT, J, movewindoworgroup, l
bind = $mainMod SHIFT, L, movewindoworgroup, d
bind = $mainMod SHIFT, K, movewindoworgroup, u
bind = $mainMod SHIFT, semicolon, movewindoworgroup, r
binde = $mainMod ALT, left,moveactive,-50 0
binde = $mainMod ALT, down,moveactive, 0 50
binde = $mainMod ALT, up,moveactive, 0 -50
binde = $mainMod ALT, right,moveactive, 50 0
binde = $mainMod ALT, J,moveactive,-50 0
binde = $mainMod ALT, L,moveactive, 0 50
binde = $mainMod ALT, K,moveactive, 0 -50
binde = $mainMod ALT, semicolon,moveactive, 50 0
binde = $mainMod CTRL, left,resizeactive,-50 0
binde = $mainMod CTRL, down,resizeactive, 0 50
binde = $mainMod CTRL, up,resizeactive, 0 -50
binde = $mainMod CTRL, right,resizeactive, 50 0
binde = $mainMod CTRL, J,resizeactive,-50 0
binde = $mainMod CTRL, L,resizeactive, 0 50
binde = $mainMod CTRL, K,resizeactive, 0 -50
binde = $mainMod CTRL, semicolon,resizeactive, 50 0
bind = $mainMod CTRL, R, submap, resize
submap = resize
binde = , left , resizeactive,-50 0
binde = , down , resizeactive, 0 50
binde = , up , resizeactive, 0 -50
binde = , right, resizeactive, 50 0
binde = , J , resizeactive,-50 0
binde = , L , resizeactive, 0 50
binde = , K , resizeactive, 0 -50
binde = , semicolon, resizeactive, 50 0
bind = ,escape, submap, reset
bind = $mainMod SHIFT, R, submap, reset
submap = reset
bind = $mainMod, 1, execr, "$focusWorkspace $activeMonitorId"1
bind = $mainMod, 2, execr, "$focusWorkspace $activeMonitorId"2
bind = $mainMod, 3, execr, "$focusWorkspace $activeMonitorId"3
bind = $mainMod, 4, execr, "$focusWorkspace $activeMonitorId"4
bind = $mainMod, 5, execr, "$focusWorkspace $activeMonitorId"5
bind = $mainMod, 6, execr, "$focusWorkspace $activeMonitorId"6
bind = $mainMod, 7, execr, "$focusWorkspace $activeMonitorId"7
bind = $mainMod, 8, execr, "$focusWorkspace $activeMonitorId"8
bind = $mainMod, 9, execr, "$focusWorkspace $activeMonitorId"9
bind = $mainMod, 0, execr, "$focusWorkspace $((1+$activeMonitorId))"0
# Move focuse inside focusing monitor
# bind = $mainMod ALT, H, execr, "$focusWorkspace" "$activeMonitorId""$(((activeWorkspaceId-1)%10))"
# bind = $mainMod ALT, L, execr, "$focusWorkspace" "$activeMonitorId""$(((activeWorkspaceId+1)%10))"
bind = $mainMod , I, execr, `if [ $(("$activeWorkspaceId" % 10)) -eq 1 ]; then "$focusWorkspace $(($activeWorkspaceId+9))"; else "$focusWorkspace $(($activeWorkspaceId-1))" ;fi`
bind = $mainMod , O, execr, `if [ $(("$activeWorkspaceId" % 10)) -eq 0 ]; then "$focusWorkspace $(($activeWorkspaceId-9))"; else "$focusWorkspace $(($activeWorkspaceId+1))" ;fi`
bind = $mainMod SHIFT, I, execr, `if [ $(("$activeWorkspaceId" % 10)) -eq 1 ]; then "$move2Workspace $(($activeWorkspaceId+9))"; else "$move2Workspace $(($activeWorkspaceId-1))" ;fi`
bind = $mainMod SHIFT, O, execr, `if [ $(("$activeWorkspaceId" % 10)) -eq 0 ]; then "$move2Workspace $(($activeWorkspaceId-9))"; else "$move2Workspace $(($activeWorkspaceId+1))" ;fi`
bind = $mainMod ALT, h, workspace, m-1
bind = $mainMod ALT, l, workspace, m+1
bind = $mainMod , Tab, workspace, previous
# bind = $mainMod , COMMA, workspace, m-1
# bind = $mainMod , PERIOD, workspace, m+1
# Move window to workspace {{{
bind = $mainMod SHIFT, 1, execr, "$move2Workspace" "$activeMonitorId"1
bind = $mainMod SHIFT, 2, execr, "$move2Workspace" "$activeMonitorId"2
bind = $mainMod SHIFT, 3, execr, "$move2Workspace" "$activeMonitorId"3
bind = $mainMod SHIFT, 4, execr, "$move2Workspace" "$activeMonitorId"4
bind = $mainMod SHIFT, 5, execr, "$move2Workspace" "$activeMonitorId"5
bind = $mainMod SHIFT, 6, execr, "$move2Workspace" "$activeMonitorId"6
bind = $mainMod SHIFT, 7, execr, "$move2Workspace" "$activeMonitorId"7
bind = $mainMod SHIFT, 8, execr, "$move2Workspace" "$activeMonitorId"8
bind = $mainMod SHIFT, 9, execr, "$move2Workspace" "$activeMonitorId"9
bind = $mainMod SHIFT, 0, execr, "$move2Workspace" "$((1+$activeMonitorId))"0
#}}}
Mouse actions to move window, resize window and swap workspaces.
# Mouse window action{{{
bindm= $mainMod, mouse:272, movewindow
bindm= $mainMod, mouse:273, resizewindow
bind = $mainMod, mouse_down, workspace, e+1
bind = $mainMod, mouse_up, workspace, e-1
#}}}
# hide an active specialWorkspace
bind = $mainMod, escape, execr, hyprctl dispatch togglespecialworkspace $specialWorkspaceId
bind = $mainMod, F1, togglespecialworkspace, 1
bind = $mainMod, F2, togglespecialworkspace, 2
bind = $mainMod, F3, togglespecialworkspace, 3
bind = $mainMod, F4, togglespecialworkspace, 4
bind = $mainMod, F5, togglespecialworkspace, 5
bind = $mainMod, F6, togglespecialworkspace, 6
bind = $mainMod, F7, togglespecialworkspace, 7
bind = $mainMod, F8, togglespecialworkspace, 8
bind = $mainMod, F9, togglespecialworkspace, 9
bind = $mainMod, F10, togglespecialworkspace, 10
bind = $mainMod, F11, togglespecialworkspace, 11
bind = $mainMod, F12, togglespecialworkspace, 12
bind = $mainMod SHIFT, S, movetoworkspace, special
bind = $mainMod SHIFT, F1, movetoworkspace, special:1
bind = $mainMod SHIFT, F2, movetoworkspace, special:2
bind = $mainMod SHIFT, F3, movetoworkspace, special:3
bind = $mainMod SHIFT, F4, movetoworkspace, special:4
bind = $mainMod SHIFT, F5, movetoworkspace, special:5
bind = $mainMod SHIFT, F6, movetoworkspace, special:6
bind = $mainMod SHIFT, F7, movetoworkspace, special:7
bind = $mainMod SHIFT, F8, movetoworkspace, special:8
bind = $mainMod SHIFT, F9, movetoworkspace, special:9
bind = $mainMod SHIFT, F10, movetoworkspace, special:10
bind = $mainMod SHIFT, F11, movetoworkspace, special:11
bind = $mainMod SHIFT, F12, movetoworkspace, special:12
#}}}
These are the windows I want to make float.
windowrule = float, ^(xdg-desktop-portal)$
windowrule = float, ^(xdg-desktop-portal-gnome)$
windowrule = float, ^(Rofi)$
windowrule = fullscreen, ^(wlogout)$
windowrule = float, ^(org.gnome.Calculator)$
windowrule = float, ^(org.gnome.Settings)$
windowrule = float, ^(org.gnome.design.Palette)$
windowrule = float, ^(eww)$
windowrule = float, ^(pavucontrol)$
windowrule = float, ^(nm-connection-editor)$
windowrule = float, ^(blueberry.py)$
windowrulev2 = float, class:^(blueman-manager)$, title: ^(Bluetooth Devices)$
windowrule = float, ^(Color Picker)$
windowrule = float, ^(Network)$
windowrule = float, ^(transmission-gtk)$
windowrule = float, ^(hmcl)$
windowrulev2 = float, class:^(thunar)$,title:^(?!.* - Thunar$).*$
windowrule = float, ^(org.fcitx.fcitx5-config-qt)
windowrule = float, ^(file-roller)$
windowrulev2 = float, class:^(feh)$
windowrulev2 = float, class:^(mpv)$
windowrulev2 = float, title:^(Media viewer)$
windowrulev2 = float, class:^(org.inkscape.Inkscape)$, title:^(Distribute Along Path)$
windowrulev2 = float, class:^(org.inkscape.Inkscape)$, title:^(Interpolate Between Paths)$
windowrulev2 = tile, class:^(com-cburch-logisim-Main)$
Some xwayland window’s menu have a dim black border by default. However hyprland applys a corner rounding to it by cutting off its 4 corners, making the corner having no border, which looks strange.
These menus have no class (class=”“). So the following rule can disable the corner rounding for them.
windowrulev2 = rounding 0, class:^()$, floating:1, xwayland:1
windowrulev2 = rounding 0, class:^(GoldenDict-ng)$, floating:1, xwayland:1
windowrulev2 = float, class:^(vlc)$,title:^(Adjustments and Effects — VLC media player)$
windowrulev2 = float, class:^(vlc)$,title:^(Simple Preferences — VLC media player)$
Steam has a friend list window. By default when opening friends list, it will be tiled together with steam, which isn’t nice. Adding this rule makes Friends list float.
windowrulev2 = float, class:^(steam)$, title:^(Friends List)
Menu’s in steam title bar’s are not interactable, when you click on an entry and try to move the pointer to the menu, the menu disappears. Adding this rule prevents the menu from disappearing.
windowrulev2 = nofocus, class:^(steam)$, title:^()$, floating:1
Bigwig Studio is a music production studio. It has buttons that are dragable. When dragging those buttons, a tiny tooltip window will float above the button showing its current value.
However, on hyprland, when dragging those buttons, this tooltip window will be auto focused, which then lead to bitwig’s window losing its focus, and the drag action failing to be recognized. Thus the button appears to be undragable.
The tooltip window’s class is “”, and it’s floating. Therefore adding the following rule fixed this issue. From my experience so far, this do not break anything else.
windowrulev2 = noinitialfocus, class:^()$, floating:1
windowrulev2 = noblur, class:fcitx
layerrule = noanim, chad-shell
animation = windowsMove, 0
Currently I have no workspace rules.