skip to content

Arch KDE -> Hyprland

/ 12 min read

Table of Contents

KDE 上 Wayland 后天天给我 crash, 就直接换 Hyprland 了

1. 安装

  1. 在 Arch KDE(或现有桌面) 下
  2. pacman hyprwayland-scanner 或 yay hyprwayland-scanner-git
  3. pacman hyprland 或 yay hyprwayland-git
  4. [Optional] 可以在 console 用 hyprland 进桌面, 但是基本什么都干不了, cmd 下的 hyprland 不会接收到我的 Super 按键事件

2. 配置

  1. 先别急着用 sddm 进 hyprland, 在 Arch KDE(或现有桌面)下
  2. 创建或更改 ~/.config/hypr/hyprland.conf, 例子 hyprwm/Hyprland, 可以直接复制覆盖
  3. 确认好基本的设置比如 Super key 是什么, terminal 有没有安装(默认是 kitty) 可能没有安装然后会导致开不了控制台基本就很难受(一般直接更改到你目前用的比如 konsole)
  4. 然后就可以进去边用边设

2.1 MONITORS

可以给显示器设置摆放位置和刷新率, 比如我放一个 AOC 在左边, 笔记本屏幕在右边

################
### MONITORS ###
################
# See https://wiki.hyprland.org/Configuring/Monitors/
monitor=,preferred,auto,1
# auto put AOC in left
monitor=desc:Chimei Innolux Corporation 0x15E8,1920x1080@60,1920x0,1
monitor=desc:AOC 27B2 0x0000CD6A,1920x1080@75,0x0,1

其中 monitor 的 description 可以在 hyprctl monitors 拿到. 尽量别设负数 position (虽然也能用), 会导致一些程序运行错误, 比如 hyprshot.

2.2 MY PROGRAMS

可以设 terminal 到你常用的

2.3 Autostart

#################
### AUTOSTART ###
#################
# Autostart necessary processes (like notifications daemons, status bars, etc.)
# Or execute your favorite apps at launch like this:
exec-once=dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP # for screen sharing
# exec-once = ~/xdg-deksop-portal-hyprland-startup.sh
exec-once = $terminal
# notification
exec-once = dunst
# status bar and background
exec-once = waybar -c ~/.config/waybar/waybar.conf
# wallpaper
exec-once = hyprpaper --config ~/.config/hypr/hyprpaper.conf
# copy-paste manager
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
# save paste content after application closed
exec-once = wl-clip-persist --clipboard regular
# KDE auth kit - auth popup
# exec-once=/usr/lib/polkit-kde-authentication-agent-1
# Or if you use Hyprland w/o uwsm
# check https://wiki.hyprland.org/Hypr-Ecosystem/hyprpolkitagent/
# exec-once = systemctl --user start hyprpolkitagent
# fcitx5 config
exec-once=fcitx5-remote -r
exec-once=fcitx5 -d --replace
exec-once=fcitx5-remote -r
# icon indicator on waybar
exec-once=nm-applet --indicator
exec-once=blueman-applet
  • wl-clipboard wl-clip-ersist waybar hyprpolkitagent 等需要额外安装, 用 pacman 或 yay
  • wl-paste 可以用来管理复制的内容, 然后用快捷键比如 Super + V 看历史
  • fcitx 解决方法参考 hyprwm/Hyprland/discussions/421

2.4 INPUT

  • kb_options 可以用来设 compose key 比如 kb_options = compose:ralt
  • follow_mouse 用来选鼠标交互方式, 比如鼠标 1=hover(放上去就选中窗口) 或者 2=click(点击选中)
  • scroll_factor 设置滚动速度

2.5 ENV

#############################
### ENVIRONMENT VARIABLES ###
#############################
# See https://wiki.hyprland.org/Configuring/Environment-variables/
# fcitx
# env = GTK_IM_MODULE,fcitx # set GTK seperately for fcitx instead of setting GTK_IM_MODULE
env = QT_IM_MODULE,fcitx
env = QT_IM_MODULES,wayland;fcitx;ibus
env = XMODIFIERS,@im=fcitx
env = SDL_IM_MODULE,fcitx
env = GLFW_IM_MODULE,ibus
env = GDK_BACKEND,wayland,x11,*
env = ELECTRON_OZONE_PLATFORM_HINT,wayland
env = QT_QPA_PLATFORM,wayland;xcb
env = SDL_VIDEODRIVER,wayland
env = CLUTTER_BACKEND,wayland
env = XCURSOR_SIZE,24
env = HYPRCURSOR_SIZE,24
env = XDG_MENU_PREFIX,arch-
env = XDG_CURRENT_DESKTOP,Hyprland
env = XDG_SESSION_TYPE,wayland
env = XDG_SESSION_DESKTOP,Hyprland
## if use Nvidia
# env = LIBVA_DRIVER_NAME,nvidia
# env = __GLX_VENDOR_LIBRARY_NAME,nvidia
# env = NVD_BACKEND,directs

2.6 KEYBINDINGSS

大部分都是默认

####################
### KEYBINDINGSS ###
####################
# See https://wiki.hyprland.org/Configuring/Keywords/
$mainMod = SUPER # Sets "Windows" key as main modifier
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
bind = $mainMod, Q, exec, $terminal
bind = $mainMod, C, killactive,
bind = $mainMod, M, exit,
bind = $mainMod, E, exec, $fileManager
bind = $mainMod, F, togglefloating,
bind = $mainMod, R, exec, $menu
# bind = $mainMod, P, pseudo, # dwindle
bind = $mainMod, P, exec, $terminal -e " python"
bind = $mainMod, J, togglesplit, # dwindle
# Move focus with mainMod + arrow keys
bind = $mainMod, left, movefocus, l
bind = $mainMod, right, movefocus, r
bind = $mainMod, up, movefocus, u
bind = $mainMod, down, movefocus, d
# bind = $mainMod, down, layoutmsg, cyclenext
# 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 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
# Example special workspace (scratchpad)
bind = $mainMod, S, togglespecialworkspace, magic
bind = $mainMod SHIFT, S, movetoworkspace, special:magic
bind = $mainMod, V, exec, cliphist list | wofi --dmenu | cliphist decode | wl-copy
# if nvidia
# bind = $mainMod, G, exec, google-chrome-stable --enable-features=UseOzonePlatform --ozone-platform=wayland --enable-wayland-ime --use-angle=vulkan --use-cmd-decoder=passthrough
bind = $mainMod, G, exec, google-chrome-stable --enable-features=UseOzonePlatform --ozone-platform=wayland --enable-wayland-ime
bind = $mainMode, K, exec, kate
bind = $mainMode, Y, exec, spotify --enable-features=UseOzonePlatform --ozone-platform=wayland --enable-wayland-ime
# Scroll through existing workspaces with mainMod + scroll
bind = $mainMod, mouse_down, workspace, e+1
bind = $mainMod, mouse_up, workspace, e-1
# Move/resize windows with mainMod + LMB/RMB and dragging
bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow
# bind=,Print,exec,hyprshot -m region --clipboard-only
# bind=,Print, exec, grimblast copy area
bind=,Print, exec,grim -g "$(slurp)" - | swappy -f -
# bindel=, XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
# bindel=, XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
bind=, XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
bind =, XF86AudioPlay, exec, playerctl play-pause
bind =, XF86AudioPause, exec, playerctl play-pause
bind =, XF86AudioNext, exec, playerctl next
bind =, XF86AudioPrev, exec, playerctl previous
bind = , XF86AudioRaiseVolume, exec, volumectl up
bind = , XF86AudioLowerVolume, exec, volumectl down
# use acpi in /etc/acpi/handlers and /etc/acpi/events
# bind = , XF86MonBrightnessUp, exec, lightctl up
# bind = , XF86MonBrightnessDown, exec, lightctl down
bind = $mainMod, L, exec, hyprlock
  • bind bindl bindm 之类的大体上没有显著差别
  • hyprshot grimblast playerctl hyprlock, swappy 等要额外安装
  • Arch 没有 lightctl 可以用 acpi 代替, 参考 ejmastnak.com/tutorials/arch/backlight

2.7 Waybar - Status Bar

  1. 创建 ~/.config/waybar/waybar.conf
  2. Alexays/Waybar/wiki/Examples 找模板改, 我改的第三个, 配置如下

waybar.json

// -*- mode: json -*-
// from https://github.com/cjbassi/config/blob/master/.config/waybar/config
{
"layer": "top",
"position": "top",
"modules-left": [
"hyprland/workspaces",
"custom/right-arrow-dark"
],
"modules-center": [
"custom/left-arrow-dark",
"clock#1",
"custom/left-arrow-light",
"custom/left-arrow-dark",
"clock#2",
"custom/right-arrow-dark",
"custom/right-arrow-light",
"clock#3",
"custom/right-arrow-dark"
],
"modules-right": [
"custom/left-arrow-dark",
"wireplumber",
"custom/left-arrow-light",
"custom/left-arrow-dark",
"memory",
"custom/left-arrow-light",
"custom/left-arrow-dark",
"cpu",
"custom/left-arrow-light",
"custom/left-arrow-dark",
"battery",
"custom/left-arrow-light",
"custom/left-arrow-dark",
"disk",
"custom/left-arrow-light",
"custom/left-arrow-dark",
"backlight",
"custom/left-arrow-light",
"custom/left-arrow-dark",
"tray"
],
"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
},
"hyprland/workspaces": {
"disable-scroll": true,
"format": "{name}",
"on-click": "activate"
},
"clock#1": {
"format": "{:%a}",
"tooltip": false
},
"clock#2": {
"format": "{:%H:%M}",
"tooltip": false
},
"clock#3": {
"format": "{:%m-%d}",
"tooltip": false
},
"wireplumber": {
"format": "{icon} {volume:2}%",
"format-bluetooth": "{icon} {volume}%",
"format-muted": "MUTE",
"format-icons": {
"headphones": "",
"default": [
"",
""
]
},
"scroll-step": 5,
"on-click": "pamixer -t",
"on-click-right": "pavucontrol"
},
"memory": {
"interval": 5,
"format": "Mem {}%"
},
"cpu": {
"interval": 5,
"format": "CPU {usage:2}%"
},
"battery": {
"states": {
"good": 95,
"warning": 30,
"critical": 15
},
"format": "{icon} {capacity}%",
"format-icons": [
"",
"",
"",
"",
""
]
},
"disk": {
"interval": 5,
"format": "Disk {percentage_used:2}%",
"path": "/"
},
"backlight": {
"format": "\udb80\udcdf {percent}%",
"scroll-step": 5
},
"tray": {
"icon-size": 20
}
}

其中 pavucontrol pamixer 得另外装
style.css

* {
font-size: 20px;
font-family: monospace;
}
window#waybar {
background: #292b2e;
color: #fdf6e3;
}
#custom-right-arrow-dark,
#custom-left-arrow-dark {
color: #1a1a1a;
}
#custom-right-arrow-light,
#custom-left-arrow-light {
color: #292b2e;
background: #1a1a1a;
}
#workspaces,
#clock.1,
#clock.2,
#clock.3,
#wireplumber,
#memory,
#cpu,
#battery,
#disk,
#backlight,
#tray {
background: #1a1a1a;
}
#workspaces button {
padding: 0 2px;
color: #fdf6e3;
}
#workspaces button.focused {
color: #268bd2;
}
#workspaces button:hover {
box-shadow: inherit;
text-shadow: inherit;
}
#workspaces button:hover {
background: #1a1a1a;
border: #1a1a1a;
padding: 0 3px;
}
#wireplumber {
color: #268bd2;
}
#memory {
color: #2aa198;
}
#cpu {
color: #6c71c4;
}
#battery {
color: #859900;
}
#disk {
color: #b58900;
}
#clock,
#wireplumber,
#memory,
#cpu,
#battery,
#disk,
#backlight{
padding: 0 10px;
}

放在 ~/.config/waybar 下然后 exec-once 里启动

2.8 Hyprlock - screen Locker

  1. 创建 ~/.config/hypr/hyprlock.conf
  2. 复制 wiki.hyprland.org/Hypr-Ecosystem/hyprlock 上 Widgets 下来, 比如
background {
monitor =
# path = /home/me/someImage.png # only png supported for now
color = rgba(25, 20, 20, 1.0)
# all these options are taken from hyprland, see https://wiki.hyprland.org/Configuring/Variables/#blur for explanations
blur_passes = 0 # 0 disables blurring
blur_size = 7
noise = 0.0117
contrast = 0.8916
brightness = 0.8172
vibrancy = 0.1696
vibrancy_darkness = 0.0
}
input-field {
monitor =
size = 200, 50
outline_thickness = 3
dots_size = 0.33 # Scale of input-field height, 0.2 - 0.8
dots_spacing = 0.15 # Scale of dots' absolute size, 0.0 - 1.0
dots_center = false
dots_rounding = -1 # -1 default circle, -2 follow input-field rounding
outer_color = rgb(151515)
inner_color = rgb(200, 200, 200)
font_color = rgb(10, 10, 10)
fade_on_empty = true
fade_timeout = 1000 # Milliseconds before fade_on_empty is triggered.
placeholder_text = <i>Input Password...</i> # Text rendered in the input box when it's empty.
hide_input = false
rounding = -1 # -1 means complete rounding (circle/oval)
check_color = rgb(204, 136, 34)
fail_color = rgb(204, 34, 34) # if authentication failed, changes outer_color and fail message color
fail_text = <i>$FAIL <b>($ATTEMPTS)</b></i> # can be set to empty
fail_transition = 300 # transition time in ms between normal outer_color and fail_color
capslock_color = -1
numlock_color = -1
bothlock_color = -1 # when both locks are active. -1 means don't change outer color (same for above)
invert_numlock = false # change color if numlock is off
swap_font_color = false # see below
position = 0, -20
halign = center
valign = center
}
label {
monitor =
text = cmd[update:1000] echo "<span foreground='blue'>$(date)</span> "
text_align = center # center/right or any value for default left. multi-line text alignment inside label container
color = rgba(200, 200, 200, 1.0)
font_size = 25
font_family = Noto Sans
rotate = 0 # degrees, counter-clockwise
position = 0, 80
halign = center
valign = center
}

2.9 Electron on wayland

本节为了解决一些 electron 应用不能复制之类的问题

参考:

  1. 如果遇到 chromium / electron 无法复制 -> 可以开 xeyes 看看是不是跑在 X11 下(用 xeyes), 要跑在 wayland 上就没问题.
  2. export ELECTRON_OZONE_PLATFORM_HINT=waylandexport QT_QPA_PLATFORM=wayland 让 electron 和 qt 程序跑在 wayland 上
  3. 如果遇到 fcitx5 无法在 chromium / elctron 在 wayland 上输入, 需要加参数 --enable-features=UseOzonePlatform --ozone-platform=wayland --enable-wayland-ime 在启动的时候, 比如 chrome 和 vscode

2.10 Screen sharing

本节为了解决不能分享屏幕或者录屏之类的问题

参考:

  1. 先按照文档1的安装 pipewirewireplumber , 然后按照文档2的安装 xdg-desktop-portal-hyprland(可以卸载 xdg-desktop-portal-wlr 如果有).
  2. 根据文档2把 exec-once=dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP 加进 hyprland.conf

2.11 打开文件 KDE 提示的弹窗

本节为了解决 KDE 提示的弹窗是空白或者他不能根据文件后缀打开

参考: https://www.lorenzobettini.it/2024/05/fixing-the-empty-open-with-in-dolphin-in-hyprland/

  1. 安装 sudo pacman -S archlinux-xdg-menu
  2. env = XDG_MENU_PREFIX,arch- 加到 hyprland.conf

2.12 Jetbrain IDEs in wayland

wayland 上跑 Jetbrain IDEs

参考:

  1. -Dawt.toolkit.name=WLToolkit 加到 help->custom VM options

2.13 Line In

如果想监听/playback主板的 LineIn 口(也就是 windows 上的 listern 功能) 可以用 pactl load-module module-loopback source=alsa_input.usb-Generic_USB_Audio-00.pro-input-1. 其中 source 需要 pactl list short sources 然后找到 LineIn 的 sink, 不行的话可以每个都试一下. 取消监听是 pactl unload-module module-loopback

3. 遇到的未解决的问题

  • Jetbrain IDEs 可能在一些操作后, 比如 Ctrl shift L 格式化后失去指针(不会显示正在更改的光标也无法输入), 目测是格式化弹窗用 enter 进行格式化而不是鼠标触发, 我一般用 Super + C 弹出 IDE 的关闭确认弹窗然后取消就可以了
  • Chrome 在跳弹窗的时候不会显示 popup 只会把 tab 冻结,用按住 SUPER 然后点一下 Chrome 就ok了