Linux - Hyprland

Introduction

Hyprland is a dynamic tiling compositor based on wlroot. Compared to sway, hyprland provides better experience and easy configuration. What is exciting, its development is much active.

Hyprland's core components and necessary applications can be simply installed and configured, e.g.,

  • hyprland: core components
  • foot: a native terminal in wayland
  • fuzzel: an application launcher
  • light: a backlight controller
  • swaync: a notification utility
  • grim: a screenshot utility
  • slurp: a region selection utility in wayland
  • swaybg: a background setting utility
  • swaylock: a utility to lock screen
  • wdisplays: an arandr counterpart in wayland
  • waybar: a bar utility in wayland
  • ttf-font-awesome: a font to display icons in waybar
  • xdg-desktop-portal-hyprland: XDG desktop handler enabling D-Bus based communication for other applications
  • qt5-wayland/qt6-wayland: Wayland support for QT

Installation

  pacman -S hyprland waybar foot fuzzel swaybg swaylock light grim slurp ttf-font-awesome qt5-wayland qt6-wayland blueman network-manager-applet pipewire wireplumber xdg-desktop-portal-hyprland xdg-desktop-portal-gtk

Configuration

By default, all the configuration files are stored in directory ~/.config/hypr.

  • ~/.config/hypr/hyprland.conf

      ########################################################################################
      AUTOGENERATED HYPR CONFIG.
      PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
      OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
      ########################################################################################
    
      #
      # Please note not all available settings / options are set here.
      # For a full list, see the wiki
      #
    
      # autogenerated = 1 # remove this line to remove the warning
    
      # See https://wiki.hyprland.org/Configuring/Monitors/
      # monitor=name,resolution,position,scale
      monitor=eDP-1,disable
      monitor=DP-1,preferred,auto,2
      
      # See https://wiki.hyprland.org/Configuring/Keywords/ for more
    
      # Execute your favorite apps at launch
      exec-once = waybar --config ~/.config/hypr/waybar/config --style ~/.config/hypr/waybar/style.css
      exec-once = swaybg -i /usr/share/backgrounds/archlinux/small.png
      exec-once = swaync --config ~/.config/hypr/swaync.json
      exec-once = fcitx5 -D
      exec-once = nm-applet
      exec-once = blueman-applet
      exec-once = /usr/lib/polkit-kde-authentication-agent-1
    
      # Source a file (multi-file configs)
      source = ~/.config/hypr/bind.conf
      source = ~/.config/hypr/env.conf
    
      # Window rules
      windowrulev2 = opacity 0.3, floating:1, class:foot
    
      misc {
          disable_hyprland_logo = true
          disable_splash_rendering = true
          focus_on_activate = true
      }
    
      # For all categories, see https://wiki.hyprland.org/Configuring/Variables/
      input {
          kb_layout = us
          kb_variant =
          kb_model =
          kb_options = caps:ctrl_modifier
          kb_rules =
          repeat_rate = 60
          repeat_delay = 300
          follow_mouse = 1
          touchpad {
              natural_scroll = yes
              disable_while_typing = true
          }
          sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
      }
    
      general {
          # See https://wiki.hyprland.org/Configuring/Variables/ for more
          gaps_in = 1
          gaps_out = 1
          border_size = 3
          col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
          col.inactive_border = rgba(595959aa)
          layout = dwindle
      }
    
      decoration {
          # See https://wiki.hyprland.org/Configuring/Variables/ for more
          rounding = 9
          drop_shadow = yes
          shadow_range = 3
          shadow_render_power = 3
          col.shadow = rgba(1a1a1aee)
      }
    
      animations {
          enabled = yes
          # Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
          bezier = myBezier, 0.05, 0.9, 0.1, 1.05
          animation = windows, 1, 8, default
          animation = windowsOut, 1, 8, default, slide
          animation = border, 1, 10, default
          animation = borderangle, 1, 8, default
          animation = fade, 1, 8, default
          animation = workspaces, 1, 8, default, fade
      }
    
      dwindle {
          # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
          pseudotile = yes # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
          preserve_split = yes # you probably want this
      }
    
      master {
          # See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
          new_is_master = true
      }
    
      gestures {
          # See https://wiki.hyprland.org/Configuring/Variables/ for more
          workspace_swipe = off
      }
    
      # Example per-device config
      # See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
      device:epic-mouse-v1 {
          sensitivity = -0.5
      }
  • ~/.config/hypr/bind.conf

      # See https://wiki.hyprland.org/Configuring/Keywords/ for more
      $mainMod = SUPER
    
      # Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
      bind = $mainMod, Q, killactive
      bind = $mainMod SHIFT, SPACE, togglefloating
      bind = $mainMod, E, togglesplit # dwindle
      bind = $mainMod, T, toggleopaque
      bind = $mainMod, F, fullscreen
    
      bind = $mainMod, Return, exec, foot --config ~/.config/hypr/foot.ini
      bind = $mainMod, D, exec, fuzzel --config ~/.config/hypr/fuzzel.ini
      bind = , Print, exec, grim $(date +'%Y%m%d-%H%M%S.png')
      bind = SHIFT, Print, exec, grim -g "$(slurp)" $(date +'%Y%m%d-%H%M%S.png')
    
      # Move focus
      bind = $mainMod, O, cyclenext
      bind = $mainMod, left, movefocus, l
      bind = $mainMod, right, movefocus, r
      bind = $mainMod, up, movefocus, u
      bind = $mainMod, down, movefocus, d
    
      # Switch workspaces
      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
    
      # Move active window to a workspace
      bind = $mainMod SHIFT, 1, movetoworkspacesilent, 1
      bind = $mainMod SHIFT, 2, movetoworkspacesilent, 2
      bind = $mainMod SHIFT, 3, movetoworkspacesilent, 3
      bind = $mainMod SHIFT, 4, movetoworkspacesilent, 4
      bind = $mainMod SHIFT, 5, movetoworkspacesilent, 5
      bind = $mainMod SHIFT, 6, movetoworkspacesilent, 6
      bind = $mainMod SHIFT, 7, movetoworkspacesilent, 7
      bind = $mainMod SHIFT, 8, movetoworkspacesilent, 8
      bind = $mainMod SHIFT, 9, movetoworkspacesilent, 9
    
      # Move/resize windows
      bind = $mainMod SHIFT, R, submap, resize_window
      submap = resize_window
      binde = , right, resizeactive, 10 0
      binde = , left, resizeactive, -10 0
      binde = , up, resizeactive, 0 -10
      binde = , down, resizeactive, 0 10
      bind = , escape, submap, reset
      submap = reset
      bindm = $mainMod, mouse:272, movewindow
      bindm = $mainMod, mouse:273, resizewindow
    
      # Adjust volume
      bindle = , XF86AudioRaiseVolume, exec, pactl set-sink-volume @DEFAULT_SINK@ +5%
      bindle = , XF86AudioLowerVolume, exec, pactl set-sink-volume @DEFAULT_SINK@ -5%
      bindle = , XF86AudioMute, exec, pactl set-sink-mute @DEFAULT_SINK@ toggle
      bindle = , XF86AudioMicMute, exec, pactl set-source-mute @DEFAULT_SOURCE@ toggle
    
      # Adjust Brightness
      bindle = , XF86MonBrightnessUp, exec, sudo light -A 5
      bindle = , XF86MonBrightnessDown, exec, sudo light -U 5
    
      # System submap: (E)xit, (H)alt, (R)eboot.
      bind = $mainMod SHIFT, E, submap, system
      submap = system
      bind = , E, exit
      bind = , L, exec, swaylock -i /usr/share/backgrounds/archlinux/small.png
      bind = , H, exec, systemctl poweroff
      bind = , R, exec, systemctl reboot
      bind = , escape, submap, reset
      submap = reset
  • ~/.config/hypr/env.conf

      env = LANG,en_US.UTF-8
      env = XCURSOR_SIZE,32
      env = GTK_IM_MODULE,fcitx
      env = QT_IM_MODULE,fcitx
      env = XMODIFIERS,@im=fcitx
      env = QT_QPA_PLATFORM,wayland
      env = MOZ_ENABLE_WAYLAND,1
      env = XAPIAN_CJK_NGRAM,1
      env = EDITOR,/usr/bin/emacsclient -a "" -t
      env = LIBSEAT_BACKEND,logind
  • ~/.config/hypr/foot.ini

      [main]
      font=JetBrains Mono:size=18
  • ~/.config/hypr/fuzzel.ini

      font=JetBrains Mono
      dpi-aware=auto
      prompt=" "
      icon-theme=Arc
      icons-enabled=yes
      fuzzy=yes
      show-actions=no
      lines=9
      width=60
      vertical-pad=0
      line-height=32
    
      [colors]
      background=fbf1c7ff
      text=32302fff
      match=ae6962ff
      selection=d5c4a1ff
      selection-text=282828ff
    
      [border]
      width=0
      radius=12
  • ~/.config/hypr/swaync.json

      {
        "$schema": "/etc/xdg/swaync/configSchema.json",
        "positionX": "right",
        "positionY": "top",
        "layer": "overlay",
        "control-center-layer": "top",
        "layer-shell": true,
        "cssPriority": "application",
        "control-center-margin-top": 0,
        "control-center-margin-bottom": 0,
        "control-center-margin-right": 0,
        "control-center-margin-left": 0,
        "notification-2fa-action": true,
        "notification-inline-replies": false,
        "notification-icon-size": 64,
        "notification-body-image-height": 100,
        "notification-body-image-width": 200,
        "timeout": 10,
        "timeout-low": 5,
        "timeout-critical": 0,
        "fit-to-screen": true,
        "control-center-width": 500,
        "control-center-height": 600,
        "notification-window-width": 300,
        "keyboard-shortcuts": true,
        "image-visibility": "when-available",
        "transition-time": 200,
        "hide-on-clear": false,
        "hide-on-action": true,
        "script-fail-notify": true,
        "scripts": {
          "example-script": {
            "exec": "echo 'Do something...'",
            "urgency": "Normal"
          },
          "example-action-script": {
            "exec": "echo 'Do something actionable!'",
            "urgency": "Normal",
            "run-on": "action"
          }
        },
        "notification-visibility": {
          "example-name": {
            "state": "muted",
            "urgency": "Low",
            "app-name": "Spotify"
          }
        },
        "widgets": [
          "inhibitors",
          "title",
          "dnd",
          "notifications"
        ],
        "widget-config": {
          "inhibitors": {
            "text": "Inhibitors",
            "button-text": "Clear All",
            "clear-all-button": true
          },
          "title": {
            "text": "Notifications",
            "clear-all-button": true,
            "button-text": "Clear All"
          },
          "dnd": {
            "text": "Do Not Disturb"
          },
          "label": {
            "max-lines": 5,
            "text": "Label Text"
          },
          "mpris": {
            "image-size": 96,
            "image-radius": 12
          }
        }
      }
  • ~/.config/hypr/waybar/config

      {
          "layer": "top",
          "modules-left": ["hyprland/workspaces"],
          "modules-center": [],
          "modules-right": ["cpu", "memory", "temperature", "backlight", "battery", "pulseaudio", "clock", "tray", "notification"],
          // Modules configuration
          "hyprland/workspaces": {
              "format": "{name}{icon}",
              "on-click": "activate",
              "sort-by-number": true
          },
          "tray": {
              "spacing": 10,
              "icon-size": 30
          },
          "clock": {
              "format": "{: %Y-%m-%d %a %H:%M}",
              "tooltip": false
          },
          "cpu": {
              "format": "{usage}% ",
              "tooltip": false
          },
          "memory": {
              "format": "{}% ",
              "tooltip": true
          },
          "temperature": {
              "critical-threshold": 80,
              "format": "{temperatureC}°C {icon}",
              "format-icons": ["", "", ""]
          },
          "backlight": {
              "format": "{percent}% {icon} ",
              // "format-icons": ["", ""]
              "format-icons": ["", "", "", "", "", "", "", "", ""]
          },
          "battery": {
              "states": {
                  // "good": 95,
                  "warning": 30,
                  "critical": 15
              },
              "format": "{capacity}% {icon} ",
              "format-charging": "{capacity}% ",
              "format-plugged": "{capacity}% ",
              "format-alt": "{time} {icon}",
              "tooltip": false,
              "format-icons": ["", "", "", "", ""]
          },
          "network": {
              "format-wifi": "{essid} ({signalStrength}%)  ",
              "format-ethernet": "{ifname}: {ipaddr}/{cidr}  ",
              "format-linked": "{ifname} (No IP)  ",
              "format-disconnected": "Disconnected ⚠ ",
              "format-alt": "{ifname}: {ipaddr}/{cidr}",
              "tooltip": false
          },
          "pulseaudio": {
              "scroll-step": 10, // %, can be a float
              "format": "{volume}% {icon} {format_source}",
              "format-bluetooth": "{volume}% {icon} {format_source}",
              "format-muted": "{volume}%  {format_source}",
              "format-source": "{volume}% ",
              "format-source-muted": "{volume}% ",
              "format-icons": {
                  "headphones": "",
                  "handsfree": "",
                  "headset": "",
                  "phone": "",
                  "portable": "",
                  "car": "",
                  "default": ["", "", ""]
              },
              "on-click": "pavucontrol"
          },
          "notification": {
              "tooltip": false,
              "format": "{icon}",
              "format‐icons": {
                   "notification": "<U+F0A2><span foreground=’red’><sup><U+F444></sup></span>",
                   "none": "<U+F0A2>",
                   "dnd‐notification": "<U+F1F7><span foreground=’red’><sup><U+F444></sup></span>",
                   "dnd‐none": "<U+F1F7>",
                   "inhibited‐notification": "<U+F0A2><span foreground=’red’><sup><U+F444></sup></span>",
                   "inhibited‐none": "<U+F0A2>",
                   "dnd‐inhibited‐notification": "<U+F1F7><span foreground=’red’><sup><U+F444></sup></span>",
                   "dnd‐inhibited‐none": "<U+F1F7>"
              },
              "return‐type": "json",
              "exec‐if": "which swaync‐client",
              "exec": "swaync‐client ‐swb",
              "on‐click": "swaync‐client ‐t ‐sw",
              "on‐click‐right": "swaync‐client ‐d ‐sw",
              "escape": true
          }
      }
  • ~/.config/hypr/waybar/style.css

      ,* {
          border: none;
          border-radius: 0;
          font-family: JetBrains Mono;
          font-size: 16px;
          min-height: 0;
      }
    
      window#waybar {
          background-color: transparent;
      }
    
      window#waybar.hidden {
          opacity: 0.3;
      }
    
      /*
      window#waybar.empty {
          background-color: transparent;
      }
      window#waybar.solo {
          background-color: #FFFFFF;
      }
      ,*/
    
      window#waybar.termite {
          background-color: #3F3F3F;
      }
    
      window#waybar.chromium {
          background-color: #000000;
          border: none;
      }
    
      #workspaces button {
          padding: 0 5px;
          background-color: transparent;
          color: #ffffff;
          border-bottom: 3px solid transparent;
      }
    
      /* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */
      #workspaces button:hover {
          background: rgba(0, 0, 0, 0.2);
          box-shadow: inherit;
          border-bottom: 3px solid #ffffff;
      }
    
      #workspaces button.active {
          background-color: #64727D;
          border-bottom: 3px solid #ffffff;
      }
    
      #workspaces button.urgent {
          background-color: #eb4d4b;
      }
    
      #mode {
          background-color: #64727D;
          border-bottom: 3px solid #ffffff;
      }
    
      #clock,
      #battery,
      #cpu,
      #memory,
      #temperature,
      #backlight,
      #network,
      #pulseaudio,
      #custom-media,
      #tray,
      #mode,
      #idle_inhibitor {
          padding: 0 10px;
          margin: 0 0px;
          color: #ffffff;
      }
    
      #clock {
          background-color: #64727D;
      }
    
      #battery {
          background-color: #ffffff;
          color: #000000;
      }
    
      #battery.charging {
          color: #ffffff;
          background-color: #26A65B;
      }
    
      @keyframes blink {
          to {
              background-color: #ffffff;
              color: #000000;
          }
      }
    
      #battery.critical:not(.charging) {
          background-color: #f53c3c;
          color: #ffffff;
          animation-name: blink;
          animation-duration: 0.5s;
          animation-timing-function: linear;
          animation-iteration-count: infinite;
          animation-direction: alternate;
      }
    
      label:focus {
          background-color: #000000;
      }
    
      #cpu {
          background-color: #2ecc71;
          color: #000000;
      }
    
      #memory {
          background-color: #9b59b6;
      }
    
      #backlight {
          background-color: #90b1b1;
      }
    
      #network {
          background-color: #2980b9;
      }
    
      #network.disconnected {
          background-color: #f53c3c;
      }
    
      #pulseaudio {
          background-color: #f1c40f;
          color: #000000;
      }
    
      #pulseaudio.muted {
          background-color: #90b1b1;
          color: #2a5c45;
      }
    
      #custom-media {
          background-color: #66cc99;
          color: #2a5c45;
          min-width: 100px;
      }
    
      #custom-media.custom-spotify {
          background-color: #66cc99;
      }
    
      #custom-media.custom-vlc {
          background-color: #ffa000;
      }
    
      #temperature {
          background-color: #f0932b;
      }
    
      #temperature.critical {
          background-color: #eb4d4b;
      }
    
      #tray {
          background-color: #2980b9;
      }
    
      #idle_inhibitor {
          background-color: #2d3436;
      }
    
      #idle_inhibitor.activated {
          background-color: #ecf0f1;
          color: #2d3436;
      }
    
      #mpd {
          background-color: #66cc99;
          color: #2a5c45;
      }
    
      #mpd.disconnected {
          background-color: #f53c3c;
      }
    
      #mpd.stopped {
          background-color: #90b1b1;
      }
    
      #mpd.paused {
          background-color: #51a37a;
      }

Startup

After the installation and configuration, hyprland can be started by running command Hyprland from a TTY after login.

Table of Contents