<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>模組五：Hyprland 配置 on Tarragon</title><link>https://tarrragon.github.io/blog/linux/dotfile/05-hyprland-config/</link><description>Recent content in 模組五：Hyprland 配置 on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Mon, 29 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/linux/dotfile/05-hyprland-config/index.xml" rel="self" type="application/rss+xml"/><item><title>Hyprland 安裝與環境建置</title><link>https://tarrragon.github.io/blog/linux/dotfile/05-hyprland-config/hyprland-installation/</link><pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/05-hyprland-config/hyprland-installation/</guid><description>&lt;p>Hyprland 的安裝分三層：compositor（負責視窗管理與畫面合成的核心程式，詳見 &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/04-window-management/wayland-explainer/" data-link-title="Wayland 顯示協議：為什麼 Hyprland 不跑在 X11 上" data-link-desc="想理解 Hyprland 底層的圖形架構、Wayland 跟 X11 的差異、XWayland 相容層、以及 2026 年 Wayland 已經是主流這件事時回來讀">Wayland 顯示協議&lt;/a>）本身、GPU 驅動、桌面配套工具。Compositor 只管視窗排列和畫面輸出，其餘功能（status bar、launcher、通知、音訊、藍牙、網路）都需要另外裝。本篇以 Arch Linux 為主要說明對象，其他發行版在最後簡述。&lt;/p>
&lt;h2 id="核心套件">核心套件&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">sudo pacman -S hyprland xorg-xwayland xdg-desktop-portal-hyprland&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>套件&lt;/th>
 &lt;th>角色&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>hyprland&lt;/code>&lt;/td>
 &lt;td>Compositor 本體，在 Arch 官方 &lt;code>extra&lt;/code> repo，不需要 AUR&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>xorg-xwayland&lt;/code>&lt;/td>
 &lt;td>X11 相容層，讓舊 X11 應用程式在 Wayland 環境裡正常運行&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>xdg-desktop-portal-hyprland&lt;/code>&lt;/td>
 &lt;td>Hyprland 專屬的 portal backend，處理 screen sharing 和檔案對話框&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>&lt;strong>[VM 可測試]&lt;/strong> 套件安裝本身在 VM 和實機上完全相同。&lt;/p>&lt;/blockquote>
&lt;h2 id="gpu-驅動">GPU 驅動&lt;/h2>
&lt;p>GPU 驅動決定 Hyprland 的渲染是走硬體加速還是軟體 fallback。AMD 和 Intel 開箱即用，NVIDIA 需要額外配置。&lt;/p>
&lt;h3 id="amd推薦開箱即用">AMD（推薦，開箱即用）&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">sudo pacman -S mesa vulkan-radeon libva-mesa-driver mesa-vdpau&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>mkinitcpio MODULES 加入：&lt;code>amdgpu&lt;/code>&lt;/p>
&lt;p>環境變數（放在 Hyprland 配置裡）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="n">env&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;LIBVA_DRIVER_NAME, radeonsi&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;VDPAU_DRIVER, radeonsi&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;AMD_VULKAN_ICD, RADV&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>AMD 是 Hyprland / Wayland 生態支援最好的 GPU。如果是新購硬體、有選擇的餘地，AMD 是最省事的選項。&lt;/p>
&lt;h3 id="intel開箱即用">Intel（開箱即用）&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">sudo pacman -S mesa vulkan-intel intel-media-driver&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>mkinitcpio MODULES 加入：&lt;code>i915&lt;/code>&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="n">env&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;LIBVA_DRIVER_NAME, iHD&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;VDPAU_DRIVER, va_gl&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Intel 內顯在 Wayland 上表現穩定，適合筆電和輕度桌面使用。&lt;/p>
&lt;h3 id="nvidia需要額外配置非官方支援">NVIDIA（需要額外配置，非官方支援）&lt;/h3>
&lt;blockquote>
&lt;p>&lt;strong>[需實機測試]&lt;/strong> NVIDIA 的所有設定在 VM 中無意義——VM 使用 virtio-gpu 或軟體渲染，不走 NVIDIA 驅動。以下步驟只在實體機有 NVIDIA 顯卡時才需要。&lt;/p>&lt;/blockquote>
&lt;p>Hyprland 官方不支援 NVIDIA，但社群有成熟的 workaround。最低版本需求：&lt;/p>
&lt;ul>
&lt;li>NVIDIA driver &amp;gt;= 555（555 引入完整 GBM 支援和 explicit sync，是 Wayland 硬體渲染的最低依賴。535 系列有 explicit sync 問題，Wayland 下容易 flicker。590+ 修復多數 HDR 和多螢幕邊界問題）&lt;/li>
&lt;li>xorg-xwayland &amp;gt;= 24.1&lt;/li>
&lt;li>wayland-protocols &amp;gt;= 1.34&lt;/li>
&lt;/ul>
&lt;p>安裝：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">sudo pacman -S nvidia-dkms nvidia-utils libva-nvidia-driver
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># 32-bit 支援（遊戲可能需要）：&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">sudo pacman -S lib32-nvidia-utils&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>mkinitcpio MODULES（依硬體配置選擇）：&lt;/p>
&lt;p>純 NVIDIA 桌機：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">MODULES=(nvidia nvidia_modeset nvidia_uvm nvidia_drm)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Intel + NVIDIA hybrid 筆電（Intel 排在 NVIDIA 前面）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">MODULES=(i915 nvidia nvidia_modeset nvidia_uvm nvidia_drm)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>更新 initramfs：&lt;/p></description><content:encoded><![CDATA[<p>Hyprland 的安裝分三層：compositor（負責視窗管理與畫面合成的核心程式，詳見 <a href="/blog/linux/dotfile/04-window-management/wayland-explainer/" data-link-title="Wayland 顯示協議：為什麼 Hyprland 不跑在 X11 上" data-link-desc="想理解 Hyprland 底層的圖形架構、Wayland 跟 X11 的差異、XWayland 相容層、以及 2026 年 Wayland 已經是主流這件事時回來讀">Wayland 顯示協議</a>）本身、GPU 驅動、桌面配套工具。Compositor 只管視窗排列和畫面輸出，其餘功能（status bar、launcher、通知、音訊、藍牙、網路）都需要另外裝。本篇以 Arch Linux 為主要說明對象，其他發行版在最後簡述。</p>
<h2 id="核心套件">核心套件</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo pacman -S hyprland xorg-xwayland xdg-desktop-portal-hyprland</span></span></code></pre></div><table>
  <thead>
      <tr>
          <th>套件</th>
          <th>角色</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>hyprland</code></td>
          <td>Compositor 本體，在 Arch 官方 <code>extra</code> repo，不需要 AUR</td>
      </tr>
      <tr>
          <td><code>xorg-xwayland</code></td>
          <td>X11 相容層，讓舊 X11 應用程式在 Wayland 環境裡正常運行</td>
      </tr>
      <tr>
          <td><code>xdg-desktop-portal-hyprland</code></td>
          <td>Hyprland 專屬的 portal backend，處理 screen sharing 和檔案對話框</td>
      </tr>
  </tbody>
</table>
<blockquote>
<p><strong>[VM 可測試]</strong> 套件安裝本身在 VM 和實機上完全相同。</p></blockquote>
<h2 id="gpu-驅動">GPU 驅動</h2>
<p>GPU 驅動決定 Hyprland 的渲染是走硬體加速還是軟體 fallback。AMD 和 Intel 開箱即用，NVIDIA 需要額外配置。</p>
<h3 id="amd推薦開箱即用">AMD（推薦，開箱即用）</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo pacman -S mesa vulkan-radeon libva-mesa-driver mesa-vdpau</span></span></code></pre></div><p>mkinitcpio MODULES 加入：<code>amdgpu</code></p>
<p>環境變數（放在 Hyprland 配置裡）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">env</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="s2">&#34;LIBVA_DRIVER_NAME, radeonsi&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="s2">&#34;VDPAU_DRIVER, radeonsi&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="s2">&#34;AMD_VULKAN_ICD, RADV&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>AMD 是 Hyprland / Wayland 生態支援最好的 GPU。如果是新購硬體、有選擇的餘地，AMD 是最省事的選項。</p>
<h3 id="intel開箱即用">Intel（開箱即用）</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo pacman -S mesa vulkan-intel intel-media-driver</span></span></code></pre></div><p>mkinitcpio MODULES 加入：<code>i915</code></p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">env</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="s2">&#34;LIBVA_DRIVER_NAME, iHD&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="s2">&#34;VDPAU_DRIVER, va_gl&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>Intel 內顯在 Wayland 上表現穩定，適合筆電和輕度桌面使用。</p>
<h3 id="nvidia需要額外配置非官方支援">NVIDIA（需要額外配置，非官方支援）</h3>
<blockquote>
<p><strong>[需實機測試]</strong> NVIDIA 的所有設定在 VM 中無意義——VM 使用 virtio-gpu 或軟體渲染，不走 NVIDIA 驅動。以下步驟只在實體機有 NVIDIA 顯卡時才需要。</p></blockquote>
<p>Hyprland 官方不支援 NVIDIA，但社群有成熟的 workaround。最低版本需求：</p>
<ul>
<li>NVIDIA driver &gt;= 555（555 引入完整 GBM 支援和 explicit sync，是 Wayland 硬體渲染的最低依賴。535 系列有 explicit sync 問題，Wayland 下容易 flicker。590+ 修復多數 HDR 和多螢幕邊界問題）</li>
<li>xorg-xwayland &gt;= 24.1</li>
<li>wayland-protocols &gt;= 1.34</li>
</ul>
<p>安裝：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo pacman -S nvidia-dkms nvidia-utils libva-nvidia-driver
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 32-bit 支援（遊戲可能需要）：</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">sudo pacman -S lib32-nvidia-utils</span></span></code></pre></div><p>mkinitcpio MODULES（依硬體配置選擇）：</p>
<p>純 NVIDIA 桌機：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">MODULES=(nvidia nvidia_modeset nvidia_uvm nvidia_drm)</span></span></code></pre></div><p>Intel + NVIDIA hybrid 筆電（Intel 排在 NVIDIA 前面）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">MODULES=(i915 nvidia nvidia_modeset nvidia_uvm nvidia_drm)</span></span></code></pre></div><p>更新 initramfs：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo mkinitcpio -P</span></span></code></pre></div><p>Modprobe 設定：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl"># /etc/modprobe.d/nvidia.conf
</span></span><span class="line"><span class="ln">2</span><span class="cl">options nvidia_drm modeset=1</span></span></code></pre></div><p>GRUB kernel parameter：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl"># /etc/default/grub
</span></span><span class="line"><span class="ln">2</span><span class="cl">GRUB_CMDLINE_LINUX_DEFAULT=&#34;... nvidia_drm.modeset=1 nvidia_drm.fbdev=1&#34;</span></span></code></pre></div><p>更新 GRUB：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo grub-mkconfig -o /boot/grub/grub.cfg</span></span></code></pre></div><p>Hyprland 配置裡的 NVIDIA 環境變數：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">env</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="s2">&#34;LIBVA_DRIVER_NAME, nvidia&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="s2">&#34;__GLX_VENDOR_LIBRARY_NAME, nvidia&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="s2">&#34;GBM_BACKEND, nvidia-drm&#34;</span><span class="p">,</span>         <span class="c1">-- 如果 Firefox crash，移除這行</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="s2">&#34;NVD_BACKEND, direct&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>Cursor 修正（NVIDIA 常見的硬體 cursor 問題）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="n">cursor</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">        <span class="n">no_hardware_cursors</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">        <span class="n">allow_dumb_copy</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><p>Suspend/resume 支援：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo systemctl <span class="nb">enable</span> nvidia-suspend.service nvidia-hibernate.service nvidia-resume.service</span></span></code></pre></div><h3 id="檢查-gpu-驅動狀態">檢查 GPU 驅動狀態</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">lspci -k <span class="p">|</span> grep -A <span class="m">3</span> VGA        <span class="c1"># 查看使用中的驅動</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">glxinfo <span class="p">|</span> grep <span class="s2">&#34;OpenGL renderer&#34;</span> <span class="c1"># 查看活躍的 renderer</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">vulkaninfo --summary             <span class="c1"># Vulkan 裝置資訊</span></span></span></code></pre></div><p>GPU 驅動相關的故障診斷（driver hang、畫面凍結、suspend/resume 後異常）見<a href="/blog/linux/dotfile/07-desktop-maintenance/" data-link-title="模組七：桌面環境維護與故障排除" data-link-desc="桌面凍結、compositor 掛了、或某個工具不回應時回來讀 — Linux 桌面的故障隔離模型、常見故障場景的恢復操作、日誌判讀與診斷工具">桌面環境維護與故障排除</a>。</p>
<h2 id="桌面配套套件">桌面配套套件</h2>
<p>Hyprland 只管視窗，以下是一個可用桌面需要的配套工具：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl">sudo pacman -S <span class="se">\
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="se"></span>  kitty waybar wofi mako <span class="se">\
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="se"></span>  polkit-gnome grim slurp wl-clipboard cliphist <span class="se">\
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="se"></span>  hyprpaper hyprlock hypridle <span class="se">\
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="se"></span>  pipewire pipewire-alsa pipewire-jack pipewire-pulse wireplumber <span class="se">\
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="se"></span>  pamixer pavucontrol brightnessctl <span class="se">\
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="se"></span>  bluez bluez-utils blueman <span class="se">\
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="se"></span>  networkmanager network-manager-applet <span class="se">\
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="se"></span>  thunar gvfs <span class="se">\
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="se"></span>  qt5-wayland qt6-wayland <span class="se">\
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="se"></span>  ttf-meslo-nerd noto-fonts noto-fonts-cjk</span></span></code></pre></div><table>
  <thead>
      <tr>
          <th>類別</th>
          <th>套件</th>
          <th>用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>終端機</td>
          <td><code>kitty</code></td>
          <td>Hyprland 預設配置使用的 terminal emulator</td>
      </tr>
      <tr>
          <td>狀態列</td>
          <td><code>waybar</code></td>
          <td>JSON config + CSS styling 的 status bar</td>
      </tr>
      <tr>
          <td>啟動器</td>
          <td><code>wofi</code></td>
          <td>Wayland 原生 app launcher</td>
      </tr>
      <tr>
          <td>通知</td>
          <td><code>mako</code></td>
          <td>輕量 notification daemon</td>
      </tr>
      <tr>
          <td>認證代理</td>
          <td><code>polkit-gnome</code></td>
          <td>GUI 權限提升（sudo 對話框）</td>
      </tr>
      <tr>
          <td>截圖</td>
          <td><code>grim</code> + <code>slurp</code></td>
          <td>截圖工具 + 選區工具</td>
      </tr>
      <tr>
          <td>剪貼簿</td>
          <td><code>wl-clipboard</code> + <code>cliphist</code></td>
          <td>剪貼簿存取 + 歷史記錄</td>
      </tr>
      <tr>
          <td>桌布</td>
          <td><code>hyprpaper</code></td>
          <td>靜態桌布</td>
      </tr>
      <tr>
          <td>鎖屏</td>
          <td><code>hyprlock</code></td>
          <td>Hyprland 配套鎖屏</td>
      </tr>
      <tr>
          <td>Idle</td>
          <td><code>hypridle</code></td>
          <td>閒置偵測（觸發鎖屏/休眠）</td>
      </tr>
      <tr>
          <td>音訊</td>
          <td><code>pipewire</code> + <code>wireplumber</code> + <code>pipewire-pulse</code></td>
          <td>音訊 server（取代 PulseAudio）</td>
      </tr>
      <tr>
          <td>音量控制</td>
          <td><code>pamixer</code>（CLI）+ <code>pavucontrol</code>（GUI）</td>
          <td>音量調整</td>
      </tr>
      <tr>
          <td>亮度</td>
          <td><code>brightnessctl</code></td>
          <td>螢幕亮度（筆電）</td>
      </tr>
      <tr>
          <td>藍牙</td>
          <td><code>bluez</code> + <code>bluez-utils</code> + <code>blueman</code></td>
          <td>藍牙協定 + GUI 管理</td>
      </tr>
      <tr>
          <td>網路</td>
          <td><code>networkmanager</code> + <code>nm-applet</code></td>
          <td>網路管理 + system tray 圖示</td>
      </tr>
      <tr>
          <td>檔案管理</td>
          <td><code>thunar</code> + <code>gvfs</code></td>
          <td>圖形檔案管理器 + 回收筒/遠端掛載</td>
      </tr>
      <tr>
          <td>Qt 相容</td>
          <td><code>qt5-wayland</code> + <code>qt6-wayland</code></td>
          <td>Qt 應用在 Wayland 下正常運行</td>
      </tr>
      <tr>
          <td>字型</td>
          <td><code>ttf-meslo-nerd</code> + <code>noto-fonts-cjk</code></td>
          <td>Nerd Font（waybar icon 需要）+ CJK 字型</td>
      </tr>
  </tbody>
</table>
<p>AUR 補充套件（用 <code>yay</code> 或 <code>paru</code>）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">yay -S grimblast-git   <span class="c1"># Hyprland 截圖 wrapper</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">yay -S swww            <span class="c1"># 動態桌布（hyprpaper 的替代）</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">yay -S rofi-wayland    <span class="c1"># 功能比 wofi 更豐富的 launcher</span></span></span></code></pre></div><blockquote>
<p><strong>[已驗證]</strong> 套件安裝在 VM 中完全可執行。waybar、wofi、mako、hyprlock 在 virtio-gpu-gl-pci 加速下正常 render（Hyprland 0.55 + UTM 4.7.5 實測）。</p>
<p><strong>[需實機測試]</strong> 藍牙（<code>bluez</code>）、亮度（<code>brightnessctl</code>）、音訊裝置偵測（<code>pipewire</code>）需要實際硬體。</p></blockquote>
<h2 id="登入管理器">登入管理器</h2>
<p>Hyprland 預設不含登入管理器。三個選項：</p>
<h3 id="從-tty-直接啟動最簡單">從 TTY 直接啟動（最簡單）</h3>
<p>登入文字介面後直接執行 <code>Hyprland</code>。建議用 wrapper script 設定必要的環境變數：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="cp">#!/bin/sh
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="cp"></span><span class="c1"># ~/start-hyprland.sh</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nb">export</span> <span class="nv">XDG_SESSION_TYPE</span><span class="o">=</span>wayland
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="nb">export</span> <span class="nv">XDG_CURRENT_DESKTOP</span><span class="o">=</span>Hyprland
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="nb">export</span> <span class="nv">XDG_SESSION_DESKTOP</span><span class="o">=</span>Hyprland
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="nb">exec</span> Hyprland</span></span></code></pre></div>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">chmod +x ~/start-hyprland.sh
</span></span><span class="line"><span class="ln">2</span><span class="cl">~/start-hyprland.sh</span></span></code></pre></div><h3 id="greetd--tuigreet推薦">greetd + tuigreet（推薦）</h3>
<p>greetd 是一個輕量的登入管理器，tuigreet 是它的 TUI 前端：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo pacman -S greetd greetd-tuigreet</span></span></code></pre></div><p>設定 <code>/etc/greetd/config.toml</code>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="ln">1</span><span class="cl"><span class="p">[</span><span class="nx">terminal</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nx">vt</span> <span class="p">=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="p">[</span><span class="nx">default_session</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="nx">command</span> <span class="p">=</span> <span class="s2">&#34;tuigreet --cmd Hyprland&#34;</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="nx">user</span> <span class="p">=</span> <span class="s2">&#34;greeter&#34;</span></span></span></code></pre></div><p>自動登入（可選）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="ln">1</span><span class="cl"><span class="p">[</span><span class="nx">initial_session</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nx">command</span> <span class="p">=</span> <span class="s2">&#34;Hyprland&#34;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nx">user</span> <span class="p">=</span> <span class="s2">&#34;yourusername&#34;</span></span></span></code></pre></div><p>啟用服務：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo systemctl <span class="nb">enable</span> greetd</span></span></code></pre></div><h3 id="sddm">SDDM</h3>
<p>如果已經有 KDE 或偏好圖形化登入介面：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo pacman -S sddm
</span></span><span class="line"><span class="ln">2</span><span class="cl">sudo systemctl <span class="nb">enable</span> sddm</span></span></code></pre></div><p>SDDM 會自動偵測到 Hyprland 並在登入畫面顯示它作為 session 選項。</p>
<blockquote>
<p><strong>[VM 可測試]</strong> 登入管理器的設定在 VM 中可完整測試。</p></blockquote>
<h2 id="首次啟動常見問題">首次啟動常見問題</h2>
<table>
  <thead>
      <tr>
          <th>症狀</th>
          <th>原因</th>
          <th>修正</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>黑屏、沒有 cursor</td>
          <td>缺少 polkit agent 或 seatd service</td>
          <td><code>sudo systemctl enable --now seatd</code> 或安裝 <code>polkit-gnome</code></td>
      </tr>
      <tr>
          <td>開不了 terminal</td>
          <td>預設 keybind 用的是 kitty，但 kitty 沒裝</td>
          <td><code>sudo pacman -S kitty</code> 或改 keybind 指向已安裝的 terminal</td>
      </tr>
      <tr>
          <td>Cursor 不見（NVIDIA）</td>
          <td>硬體 cursor 問題</td>
          <td>設定 <code>cursor { no_hardware_cursors = true }</code></td>
      </tr>
      <tr>
          <td>Portal 衝突，screen share 失敗</td>
          <td>同時裝了多個 portal backend</td>
          <td>移除 <code>xdg-desktop-portal-gnome</code> 和 <code>xdg-desktop-portal-gtk</code></td>
      </tr>
      <tr>
          <td>沒有音訊</td>
          <td>PipeWire 服務未啟動</td>
          <td><code>systemctl --user enable --now pipewire wireplumber</code></td>
      </tr>
      <tr>
          <td>Config 報錯但不影響使用</td>
          <td>自動產生的預設 config 語法不完整</td>
          <td>emergency keybind 仍可用：SUPER+Q 開 terminal、SUPER+M 離開</td>
      </tr>
  </tbody>
</table>
<h2 id="配置格式lua-取代-hyprlangv055">配置格式：Lua 取代 hyprlang（v0.55+）</h2>
<p>Hyprland v0.55（2026 年 4 月）起，配置格式從 hyprlang（<code>.conf</code>）遷移到 <strong>Lua</strong>（<code>.lua</code>）。舊的 <code>hyprland.conf</code> 在沒有 <code>.lua</code> 檔案時仍然可用，但 hyprlang 已被標記為 deprecated，預計在後續版本移除。</p>
<table>
  <thead>
      <tr>
          <th>格式</th>
          <th>檔案</th>
          <th>狀態</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Lua（新）</td>
          <td><code>~/.config/hypr/hyprland.lua</code></td>
          <td>推薦</td>
      </tr>
      <tr>
          <td>hyprlang（舊）</td>
          <td><code>~/.config/hypr/hyprland.conf</code></td>
          <td>deprecated</td>
      </tr>
  </tbody>
</table>
<p>遷移工具：<code>hyprlang2lua</code>（Go，有瀏覽器版）、<code>hyprconf2lua</code>（Python pip）、<code>hypr-migrate</code>。</p>
<p>本系列後續文章（<a href="/blog/linux/dotfile/05-hyprland-config/hyprland-core-config/" data-link-title="Hyprland 核心配置" data-link-desc="Hyprland 的配置檔該怎麼組織、monitor 怎麼設定、keybind 怎麼設計、輸入裝置和環境變數怎麼配時回來讀">Hyprland 核心配置</a>、<a href="/blog/linux/dotfile/05-hyprland-config/workspace-rules-appearance/" data-link-title="Workspace、Window Rules 與外觀" data-link-desc="Hyprland 的 workspace 綁定螢幕、window rules 設定浮動例外、外觀動畫調教、layout 選型、autostart 和 plugin 管理時回來讀">Workspace 與外觀</a>、<a href="/blog/linux/dotfile/06-rice-design/caelestia-overview/" data-link-title="Caelestia 總覽：預組裝的 Hyprland 桌面 Shell" data-link-desc="考慮用 Caelestia 取代手動拼裝 waybar&#43;wofi&#43;mako、或評估預組裝桌面 shell 的 trade-off 時回來讀">Caelestia</a>）都使用 Lua 格式。如果在網路上看到 <code>.conf</code> 格式的教學，多數仍然可用，但建議儘早遷移到 Lua。</p>
<p>拆分配置用 Lua 原生的 <code>require()</code>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">-- hyprland.lua</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">&#34;keybinds&#34;</span><span class="p">)</span>    <span class="c1">-- 載入同目錄下的 keybinds.lua</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">&#34;rules&#34;</span><span class="p">)</span>       <span class="c1">-- 載入同目錄下的 rules.lua</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">&#34;appearance&#34;</span><span class="p">)</span></span></span></code></pre></div><p>詳細的配置語法和設定邏輯在<a href="/blog/linux/dotfile/05-hyprland-config/hyprland-core-config/" data-link-title="Hyprland 核心配置" data-link-desc="Hyprland 的配置檔該怎麼組織、monitor 怎麼設定、keybind 怎麼設計、輸入裝置和環境變數怎麼配時回來讀">核心配置</a>和 <a href="/blog/linux/dotfile/05-hyprland-config/workspace-rules-appearance/" data-link-title="Workspace、Window Rules 與外觀" data-link-desc="Hyprland 的 workspace 綁定螢幕、window rules 設定浮動例外、外觀動畫調教、layout 選型、autostart 和 plugin 管理時回來讀">Workspace、Window Rules 與外觀</a>。</p>
<h2 id="其他發行版">其他發行版</h2>
<h3 id="fedora">Fedora</h3>
<p>Fedora 39 起即在官方 repo。安裝：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo dnf install hyprland</span></span></code></pre></div><p>JaKooLit 提供自動化安裝腳本（<code>github.com/JaKooLit/Fedora-Hyprland</code>），Fedora 42+ 運作良好。</p>
<h3 id="nixos">NixOS</h3>
<p>NixOS 有官方 module，在 <code>configuration.nix</code> 加入：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">programs</span><span class="o">.</span><span class="n">hyprland</span><span class="o">.</span><span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span></span></span></code></pre></div><p>Home Manager 也有對應 module，可以宣告式管理 Hyprland 配置。</p>
<h3 id="ubuntu">Ubuntu</h3>
<p>不推薦。Ubuntu 的 point-release 模型跟 Hyprland 的 bleeding-edge 更新節奏衝突。沒有官方 PPA，從 source 編譯可行但維護成本高。如果一定要用 Debian 系，Arch 的 rolling release 或 Fedora 的半年週期更適合 Hyprland。</p>
<h2 id="安裝後的下一步">安裝後的下一步</h2>
<p>安裝完成後，VM 環境的額外設定（環境變數、效能調整、測試矩陣）見 <a href="/blog/linux/dotfile/05-hyprland-config/hyprland-vm-setup/" data-link-title="Hyprland VM 環境設定與測試矩陣" data-link-desc="要在 VM 裡測試 Hyprland 配置、或判斷某個設定該在 VM 還是實機驗證時回來讀">VM 環境設定與測試矩陣</a>。配置檔的組織方式和 keybind 設計見 <a href="/blog/linux/dotfile/05-hyprland-config/hyprland-core-config/" data-link-title="Hyprland 核心配置" data-link-desc="Hyprland 的配置檔該怎麼組織、monitor 怎麼設定、keybind 怎麼設計、輸入裝置和環境變數怎麼配時回來讀">Hyprland 核心配置</a>。</p>
]]></content:encoded></item><item><title>Hyprland 核心配置</title><link>https://tarrragon.github.io/blog/linux/dotfile/05-hyprland-config/hyprland-core-config/</link><pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/05-hyprland-config/hyprland-core-config/</guid><description>&lt;p>Hyprland v0.55+ 使用 Lua 作為配置語言。Lua 語法基礎見 &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/lua-scripting-language/" data-link-title="Lua 腳本語言" data-link-desc="在 Hyprland 或 Neovim 配置檔遇到 Lua 語法看不懂時回來讀 — 配置檔需要的最小 Lua 知識">Lua 腳本語言&lt;/a>。&lt;/p>
&lt;h2 id="配置檔位置與格式">配置檔位置與格式&lt;/h2>
&lt;p>Hyprland v0.55 起，配置格式從 hyprlang（&lt;code>.conf&lt;/code>）遷移到 &lt;strong>Lua&lt;/strong>（&lt;code>.lua&lt;/code>）。主配置檔是 &lt;code>~/.config/hypr/hyprland.lua&lt;/code>。如果 &lt;code>.lua&lt;/code> 不存在但 &lt;code>.conf&lt;/code> 存在，Hyprland 會回退讀取舊格式，但 hyprlang 已標記為棄用，後續版本會移除支援。&lt;/p>
&lt;p>修改後即時生效（不需要重新登入或重啟）。第一次啟動時如果沒有配置檔，Hyprland 會自動產生範例配置。即使配置有語法錯誤，緊急快捷鍵（SUPER+Q 開 terminal、SUPER+M 離開）仍然可用。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>[VM 可測試]&lt;/strong> 配置檔格式和載入行為在 VM 裡跟實機完全相同。&lt;/p>&lt;/blockquote>
&lt;h3 id="模組化拆分">模組化拆分&lt;/h3>
&lt;p>用 Lua 原生的 &lt;code>require()&lt;/code> 拆分配置：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1">-- ~/.config/hypr/hyprland.lua — 主入口&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="n">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;monitors&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- 載入 monitors.lua&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="n">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;keybinds&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- 載入 keybinds.lua&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="n">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;rules&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- 載入 rules.lua&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="n">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;autostart&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- 載入 autostart.lua&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="n">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;appearance&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- 載入 appearance.lua&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="n">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;env&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">-- 載入 env.lua&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>require(&amp;quot;monitors&amp;quot;)&lt;/code> 會從同目錄載入 &lt;code>monitors.lua&lt;/code>。拆分的理由是職責分離——改 keybind 不用在千行配置裡找位置，每個子檔案可以獨立 diff 和 rollback。&lt;/p>
&lt;h3 id="從舊格式遷移">從舊格式遷移&lt;/h3>
&lt;p>Hyprland 官方提供遷移工具：&lt;code>hyprlang2lua&lt;/code>（Go，也有瀏覽器版）和 &lt;code>hypr-migrate&lt;/code>。如果你是從零開始，直接用 Lua 格式。&lt;/p>
&lt;h2 id="monitor-設定">Monitor 設定&lt;/h2>
&lt;p>Monitor 設定是硬體相關的核心配置，每台機器都不同。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1">-- ~/.config/hypr/monitors.lua&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="n">hl.config&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> &lt;span class="n">monitor&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="c1">-- 語法：&amp;#34;name, resolution@refreshrate, position, scale&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;DP-1, 2560x1440@144, 0x0, 1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;HDMI-A-1, 1920x1080@60, 2560x0, 1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="c1">-- 筆電內建螢幕&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;eDP-1, preferred, auto, 1.5&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="c1">-- 預設規則（未明確列出的螢幕）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;, preferred, auto, 1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="c1">-- 鏡像模式（DP-2 鏡像 DP-1 的畫面）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="c1">-- &amp;#34;DP-2, preferred, auto, 1, mirror, DP-1&amp;#34;,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="p">})&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>position&lt;/code> 決定多螢幕的空間排列——&lt;code>0x0&lt;/code> 是左上角原點，&lt;code>2560x0&lt;/code> 表示在第一個螢幕的右邊。&lt;code>scale&lt;/code> 處理 HiDPI 顯示（1.5 表示 150% 縮放）。&lt;/p>
&lt;p>查詢可用的 monitor 名稱：&lt;code>hyprctl monitors&lt;/code>&lt;/p>
&lt;p>其他選項：&lt;/p>
&lt;ul>
&lt;li>&lt;code>transform, 1&lt;/code> — 旋轉（0=正常、1=90 度、2=180 度、3=270 度）&lt;/li>
&lt;li>&lt;code>vrr, 1&lt;/code> — 可變更新率（1=開啟、2=僅全螢幕）&lt;/li>
&lt;li>&lt;code>bitdepth, 10&lt;/code> — 10-bit 色彩&lt;/li>
&lt;/ul>
&lt;h3 id="筆電合蓋行為">筆電合蓋行為&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1">-- 合蓋時關閉內建螢幕、開蓋時恢復&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1">-- bindl = 即使輸入鎖定也能觸發（合蓋時需要）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="n">hl.bindl&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;switch:on:Lid Switch&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;exec&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;hyprctl keyword monitor &amp;#39;eDP-1, disable&amp;#39;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="n">hl.bindl&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;switch:off:Lid Switch&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;exec&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;hyprctl keyword monitor &amp;#39;eDP-1, preferred, auto, 1&amp;#39;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>[需實機測試]&lt;/strong> Monitor 位置排列、HiDPI 縮放、VRR、旋轉、多螢幕熱插拔、合蓋行為。VM 通常只有一個虛擬螢幕。&lt;/p></description><content:encoded><![CDATA[<p>Hyprland v0.55+ 使用 Lua 作為配置語言。Lua 語法基礎見 <a href="/blog/linux/dotfile/knowledge-cards/lua-scripting-language/" data-link-title="Lua 腳本語言" data-link-desc="在 Hyprland 或 Neovim 配置檔遇到 Lua 語法看不懂時回來讀 — 配置檔需要的最小 Lua 知識">Lua 腳本語言</a>。</p>
<h2 id="配置檔位置與格式">配置檔位置與格式</h2>
<p>Hyprland v0.55 起，配置格式從 hyprlang（<code>.conf</code>）遷移到 <strong>Lua</strong>（<code>.lua</code>）。主配置檔是 <code>~/.config/hypr/hyprland.lua</code>。如果 <code>.lua</code> 不存在但 <code>.conf</code> 存在，Hyprland 會回退讀取舊格式，但 hyprlang 已標記為棄用，後續版本會移除支援。</p>
<p>修改後即時生效（不需要重新登入或重啟）。第一次啟動時如果沒有配置檔，Hyprland 會自動產生範例配置。即使配置有語法錯誤，緊急快捷鍵（SUPER+Q 開 terminal、SUPER+M 離開）仍然可用。</p>
<blockquote>
<p><strong>[VM 可測試]</strong> 配置檔格式和載入行為在 VM 裡跟實機完全相同。</p></blockquote>
<h3 id="模組化拆分">模組化拆分</h3>
<p>用 Lua 原生的 <code>require()</code> 拆分配置：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">-- ~/.config/hypr/hyprland.lua — 主入口</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">&#34;monitors&#34;</span><span class="p">)</span>      <span class="c1">-- 載入 monitors.lua</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">&#34;keybinds&#34;</span><span class="p">)</span>      <span class="c1">-- 載入 keybinds.lua</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">&#34;rules&#34;</span><span class="p">)</span>         <span class="c1">-- 載入 rules.lua</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">&#34;autostart&#34;</span><span class="p">)</span>     <span class="c1">-- 載入 autostart.lua</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">&#34;appearance&#34;</span><span class="p">)</span>    <span class="c1">-- 載入 appearance.lua</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">&#34;env&#34;</span><span class="p">)</span>           <span class="c1">-- 載入 env.lua</span></span></span></code></pre></div><p><code>require(&quot;monitors&quot;)</code> 會從同目錄載入 <code>monitors.lua</code>。拆分的理由是職責分離——改 keybind 不用在千行配置裡找位置，每個子檔案可以獨立 diff 和 rollback。</p>
<h3 id="從舊格式遷移">從舊格式遷移</h3>
<p>Hyprland 官方提供遷移工具：<code>hyprlang2lua</code>（Go，也有瀏覽器版）和 <code>hypr-migrate</code>。如果你是從零開始，直接用 Lua 格式。</p>
<h2 id="monitor-設定">Monitor 設定</h2>
<p>Monitor 設定是硬體相關的核心配置，每台機器都不同。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">-- ~/.config/hypr/monitors.lua</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="n">monitor</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="c1">-- 語法：&#34;name, resolution@refreshrate, position, scale&#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="s2">&#34;DP-1, 2560x1440@144, 0x0, 1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="s2">&#34;HDMI-A-1, 1920x1080@60, 2560x0, 1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="c1">-- 筆電內建螢幕</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="s2">&#34;eDP-1, preferred, auto, 1.5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="c1">-- 預設規則（未明確列出的螢幕）</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="s2">&#34;, preferred, auto, 1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="c1">-- 鏡像模式（DP-2 鏡像 DP-1 的畫面）</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="c1">-- &#34;DP-2, preferred, auto, 1, mirror, DP-1&#34;,</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><p><code>position</code> 決定多螢幕的空間排列——<code>0x0</code> 是左上角原點，<code>2560x0</code> 表示在第一個螢幕的右邊。<code>scale</code> 處理 HiDPI 顯示（1.5 表示 150% 縮放）。</p>
<p>查詢可用的 monitor 名稱：<code>hyprctl monitors</code></p>
<p>其他選項：</p>
<ul>
<li><code>transform, 1</code> — 旋轉（0=正常、1=90 度、2=180 度、3=270 度）</li>
<li><code>vrr, 1</code> — 可變更新率（1=開啟、2=僅全螢幕）</li>
<li><code>bitdepth, 10</code> — 10-bit 色彩</li>
</ul>
<h3 id="筆電合蓋行為">筆電合蓋行為</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">-- 合蓋時關閉內建螢幕、開蓋時恢復</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1">-- bindl = 即使輸入鎖定也能觸發（合蓋時需要）</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="n">hl.bindl</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;switch:on:Lid Switch&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;hyprctl keyword monitor &#39;eDP-1, disable&#39;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="n">hl.bindl</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;switch:off:Lid Switch&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;hyprctl keyword monitor &#39;eDP-1, preferred, auto, 1&#39;&#34;</span><span class="p">)</span></span></span></code></pre></div><blockquote>
<p><strong>[需實機測試]</strong> Monitor 位置排列、HiDPI 縮放、VRR、旋轉、多螢幕熱插拔、合蓋行為。VM 通常只有一個虛擬螢幕。</p></blockquote>
<h3 id="dotfile-管理策略">Dotfile 管理策略</h3>
<p>Monitor 設定是典型的「機器專屬」配置。如果用 chezmoi，可以用 template 依機器名稱切換；如果用 stow，可以把 <code>monitors.lua</code> 排除在 Git 外、每台機器手動寫。</p>
<h2 id="輸入裝置配置">輸入裝置配置</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">-- ~/.config/hypr/hyprland.lua 或拆到獨立檔案</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="n">input</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="n">kb_layout</span> <span class="o">=</span> <span class="s2">&#34;us&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="c1">-- 多語系：kb_layout = &#34;us,de&#34;,</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="c1">-- 切換：kb_options = &#34;grp:alt_shift_toggle&#34;,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="c1">-- Caps Lock 當 Escape：kb_options = &#34;caps:escape&#34;,</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="n">kb_options</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="n">follow_mouse</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>         <span class="c1">-- 焦點跟隨滑鼠</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="n">sensitivity</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>          <span class="c1">-- -1.0 到 1.0（0 = 不修改）</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="n">accel_profile</span> <span class="o">=</span> <span class="s2">&#34;flat&#34;</span><span class="p">,</span>   <span class="c1">-- flat 或 adaptive</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="n">repeat_rate</span> <span class="o">=</span> <span class="mi">25</span><span class="p">,</span>         <span class="c1">-- 長按時每秒重複幾次</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="n">repeat_delay</span> <span class="o">=</span> <span class="mi">600</span><span class="p">,</span>       <span class="c1">-- 按住多久開始重複（毫秒）</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="n">touchpad</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">            <span class="n">natural_scroll</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">            <span class="n">disable_while_typing</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">            <span class="p">[</span><span class="s2">&#34;tap-to-click&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">            <span class="n">drag_lock</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">            <span class="n">scroll_factor</span> <span class="o">=</span> <span class="mf">1.0</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><p>可用的 XKB options 查詢：<code>/usr/share/X11/xkb/rules/evdev.lst</code> 或 <code>localectl list-x11-keymap-options</code>。</p>
<blockquote>
<p><strong>[VM 可測試]</strong> 鍵盤 layout、repeat rate。<br>
<strong>[需實機測試]</strong> 觸控板設定、手勢、滑鼠靈敏度/加速曲線、多鍵盤配置。</p></blockquote>
<h2 id="keybind-設計">Keybind 設計</h2>
<h3 id="修飾鍵modifiersuper-是哪顆鍵">修飾鍵（Modifier）：<code>SUPER</code> 是哪顆鍵</h3>
<p>keybind 由「修飾鍵 + 按鍵」組成，Hyprland 配置裡最常當主修飾鍵的是 <code>SUPER</code>。<code>SUPER</code> 是 X11/Wayland 對 <strong>Meta 鍵</strong>的稱呼，在不同鍵盤上是不同的實體鍵：</p>
<ul>
<li><strong>PC 鍵盤</strong>：<strong>Windows 鍵</strong>（⊞，通常在 Ctrl 與 Alt 之間）。</li>
<li><strong>Mac 鍵盤</strong>：<strong>Command 鍵（⌘）</strong>。</li>
</ul>
<p>其他常見修飾鍵：<code>SHIFT</code>、<code>CTRL</code>（Control）、<code>ALT</code>（Mac 上是 Option ⌥）。組合寫法用空格串，例如 <code>&quot;SUPER SHIFT&quot;</code>。選 <code>SUPER</code> 當主修飾鍵是慣例——它幾乎不跟應用程式本身的快捷鍵衝突（應用多用 Ctrl / Alt）。</p>
<p>在 Mac 上跑虛擬機時，實體 ⌘ 會對應到 guest 的 <code>SUPER</code>，但 macOS 會先攔截部分 ⌘ 組合——這層 VM 專屬的坑見 <a href="../hyprland-vm-setup/">VM 環境設定</a>。</p>
<h3 id="bind-類型">Bind 類型</h3>
<p>Hyprland 提供多種 bind 函式，處理不同互動模式：</p>
<table>
  <thead>
      <tr>
          <th>函式</th>
          <th>行為</th>
          <th>適用場景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>hl.bind()</code></td>
          <td>按一次觸發</td>
          <td>多數快捷鍵</td>
      </tr>
      <tr>
          <td><code>hl.binde()</code></td>
          <td>長按連續觸發</td>
          <td>調整視窗大小、音量</td>
      </tr>
      <tr>
          <td><code>hl.bindm()</code></td>
          <td>滑鼠綁定</td>
          <td>拖曳移動 / 調整視窗</td>
      </tr>
      <tr>
          <td><code>hl.bindr()</code></td>
          <td>放開時觸發</td>
          <td>切換模式</td>
      </tr>
      <tr>
          <td><code>hl.bindl()</code></td>
          <td>輸入鎖定也觸發</td>
          <td>合蓋開關、鎖屏時的媒體鍵</td>
      </tr>
      <tr>
          <td><code>hl.bindel()</code></td>
          <td>連續 + 鎖定</td>
          <td>鎖屏時的音量鍵（長按連續、鎖定可用）</td>
      </tr>
  </tbody>
</table>
<blockquote>
<p><strong>[VM 可測試]</strong> 所有 keybind 邏輯和配置語法。</p></blockquote>
<h3 id="基本操作">基本操作</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">-- ~/.config/hypr/keybinds.lua</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1">-- 基本操作</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;Return&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;kitty&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;Q&#34;</span><span class="p">,</span> <span class="s2">&#34;killactive&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;D&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;wofi --show drun&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;F&#34;</span><span class="p">,</span> <span class="s2">&#34;fullscreen&#34;</span><span class="p">,</span> <span class="s2">&#34;0&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER SHIFT&#34;</span><span class="p">,</span> <span class="s2">&#34;Space&#34;</span><span class="p">,</span> <span class="s2">&#34;togglefloating&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1">-- 焦點移動（vim 風格）</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;H&#34;</span><span class="p">,</span> <span class="s2">&#34;movefocus&#34;</span><span class="p">,</span> <span class="s2">&#34;l&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;J&#34;</span><span class="p">,</span> <span class="s2">&#34;movefocus&#34;</span><span class="p">,</span> <span class="s2">&#34;d&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;K&#34;</span><span class="p">,</span> <span class="s2">&#34;movefocus&#34;</span><span class="p">,</span> <span class="s2">&#34;u&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;L&#34;</span><span class="p">,</span> <span class="s2">&#34;movefocus&#34;</span><span class="p">,</span> <span class="s2">&#34;r&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1">-- 視窗移動</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER SHIFT&#34;</span><span class="p">,</span> <span class="s2">&#34;H&#34;</span><span class="p">,</span> <span class="s2">&#34;movewindow&#34;</span><span class="p">,</span> <span class="s2">&#34;l&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER SHIFT&#34;</span><span class="p">,</span> <span class="s2">&#34;J&#34;</span><span class="p">,</span> <span class="s2">&#34;movewindow&#34;</span><span class="p">,</span> <span class="s2">&#34;d&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER SHIFT&#34;</span><span class="p">,</span> <span class="s2">&#34;K&#34;</span><span class="p">,</span> <span class="s2">&#34;movewindow&#34;</span><span class="p">,</span> <span class="s2">&#34;u&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER SHIFT&#34;</span><span class="p">,</span> <span class="s2">&#34;L&#34;</span><span class="p">,</span> <span class="s2">&#34;movewindow&#34;</span><span class="p">,</span> <span class="s2">&#34;r&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="c1">-- 視窗大小調整（長按連續觸發）</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="n">hl.binde</span><span class="p">(</span><span class="s2">&#34;SUPER CTRL&#34;</span><span class="p">,</span> <span class="s2">&#34;H&#34;</span><span class="p">,</span> <span class="s2">&#34;resizeactive&#34;</span><span class="p">,</span> <span class="s2">&#34;-20 0&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="n">hl.binde</span><span class="p">(</span><span class="s2">&#34;SUPER CTRL&#34;</span><span class="p">,</span> <span class="s2">&#34;J&#34;</span><span class="p">,</span> <span class="s2">&#34;resizeactive&#34;</span><span class="p">,</span> <span class="s2">&#34;0 20&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="n">hl.binde</span><span class="p">(</span><span class="s2">&#34;SUPER CTRL&#34;</span><span class="p">,</span> <span class="s2">&#34;K&#34;</span><span class="p">,</span> <span class="s2">&#34;resizeactive&#34;</span><span class="p">,</span> <span class="s2">&#34;0 -20&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="n">hl.binde</span><span class="p">(</span><span class="s2">&#34;SUPER CTRL&#34;</span><span class="p">,</span> <span class="s2">&#34;L&#34;</span><span class="p">,</span> <span class="s2">&#34;resizeactive&#34;</span><span class="p">,</span> <span class="s2">&#34;20 0&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="c1">-- 滑鼠綁定：SUPER + 左鍵拖曳移動、右鍵拖曳調整大小</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="n">hl.bindm</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;mouse:272&#34;</span><span class="p">,</span> <span class="s2">&#34;movewindow&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="n">hl.bindm</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;mouse:273&#34;</span><span class="p">,</span> <span class="s2">&#34;resizewindow&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="c1">-- Workspace 切換</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;1&#34;</span><span class="p">,</span> <span class="s2">&#34;workspace&#34;</span><span class="p">,</span> <span class="s2">&#34;1&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;2&#34;</span><span class="p">,</span> <span class="s2">&#34;workspace&#34;</span><span class="p">,</span> <span class="s2">&#34;2&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;3&#34;</span><span class="p">,</span> <span class="s2">&#34;workspace&#34;</span><span class="p">,</span> <span class="s2">&#34;3&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;4&#34;</span><span class="p">,</span> <span class="s2">&#34;workspace&#34;</span><span class="p">,</span> <span class="s2">&#34;4&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;5&#34;</span><span class="p">,</span> <span class="s2">&#34;workspace&#34;</span><span class="p">,</span> <span class="s2">&#34;5&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;6&#34;</span><span class="p">,</span> <span class="s2">&#34;workspace&#34;</span><span class="p">,</span> <span class="s2">&#34;6&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;7&#34;</span><span class="p">,</span> <span class="s2">&#34;workspace&#34;</span><span class="p">,</span> <span class="s2">&#34;7&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;8&#34;</span><span class="p">,</span> <span class="s2">&#34;workspace&#34;</span><span class="p">,</span> <span class="s2">&#34;8&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;9&#34;</span><span class="p">,</span> <span class="s2">&#34;workspace&#34;</span><span class="p">,</span> <span class="s2">&#34;9&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">
</span></span><span class="line"><span class="ln">43</span><span class="cl"><span class="c1">-- 把視窗送到指定 workspace</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER SHIFT&#34;</span><span class="p">,</span> <span class="s2">&#34;1&#34;</span><span class="p">,</span> <span class="s2">&#34;movetoworkspace&#34;</span><span class="p">,</span> <span class="s2">&#34;1&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER SHIFT&#34;</span><span class="p">,</span> <span class="s2">&#34;2&#34;</span><span class="p">,</span> <span class="s2">&#34;movetoworkspace&#34;</span><span class="p">,</span> <span class="s2">&#34;2&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">46</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER SHIFT&#34;</span><span class="p">,</span> <span class="s2">&#34;3&#34;</span><span class="p">,</span> <span class="s2">&#34;movetoworkspace&#34;</span><span class="p">,</span> <span class="s2">&#34;3&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl"><span class="c1">-- 以此類推</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">
</span></span><span class="line"><span class="ln">49</span><span class="cl"><span class="c1">-- 螢幕截圖</span>
</span></span><span class="line"><span class="ln">50</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;Print&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;grimblast copy area&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;Print&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;grimblast copy output&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">52</span><span class="cl">
</span></span><span class="line"><span class="ln">53</span><span class="cl"><span class="c1">-- 多螢幕焦點切換</span>
</span></span><span class="line"><span class="ln">54</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;comma&#34;</span><span class="p">,</span> <span class="s2">&#34;focusmonitor&#34;</span><span class="p">,</span> <span class="s2">&#34;l&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">55</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;period&#34;</span><span class="p">,</span> <span class="s2">&#34;focusmonitor&#34;</span><span class="p">,</span> <span class="s2">&#34;r&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">56</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER SHIFT&#34;</span><span class="p">,</span> <span class="s2">&#34;comma&#34;</span><span class="p">,</span> <span class="s2">&#34;movewindow&#34;</span><span class="p">,</span> <span class="s2">&#34;mon:l&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">57</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER SHIFT&#34;</span><span class="p">,</span> <span class="s2">&#34;period&#34;</span><span class="p">,</span> <span class="s2">&#34;movewindow&#34;</span><span class="p">,</span> <span class="s2">&#34;mon:r&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="設計原則">設計原則</h3>
<ul>
<li><strong>SUPER</strong>（Windows/Command 鍵）當 modifier，避免跟應用程式快捷鍵衝突</li>
<li><strong>方向操作</strong>統一用 vim 的 HJKL，降低記憶負擔</li>
<li><strong>modifier 分層</strong>：SUPER 是焦點、SUPER+SHIFT 是移動、SUPER+CTRL 是調整大小</li>
<li>常用操作（開 terminal、關視窗、切 workspace）放在最順手的位置</li>
</ul>
<h3 id="submap模態快捷鍵">Submap：模態快捷鍵</h3>
<p>Submap 類似 vim 的模式切換——進入某個 submap 後，快捷鍵的意義改變，直到離開。適合需要連續操作的場景（如調整大小）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">-- 按 SUPER+R 進入 resize 模式</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;SUPER&#34;</span><span class="p">,</span> <span class="s2">&#34;R&#34;</span><span class="p">,</span> <span class="s2">&#34;submap&#34;</span><span class="p">,</span> <span class="s2">&#34;resize&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1">-- 定義 resize 模式的快捷鍵</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">hl.submap</span><span class="p">(</span><span class="s2">&#34;resize&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="n">hl.binde</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;H&#34;</span><span class="p">,</span> <span class="s2">&#34;resizeactive&#34;</span><span class="p">,</span> <span class="s2">&#34;-20 0&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="n">hl.binde</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;L&#34;</span><span class="p">,</span> <span class="s2">&#34;resizeactive&#34;</span><span class="p">,</span> <span class="s2">&#34;20 0&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="n">hl.binde</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;K&#34;</span><span class="p">,</span> <span class="s2">&#34;resizeactive&#34;</span><span class="p">,</span> <span class="s2">&#34;0 -20&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="n">hl.binde</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;J&#34;</span><span class="p">,</span> <span class="s2">&#34;resizeactive&#34;</span><span class="p">,</span> <span class="s2">&#34;0 20&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="n">hl.bind</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;escape&#34;</span><span class="p">,</span> <span class="s2">&#34;submap&#34;</span><span class="p">,</span> <span class="s2">&#34;reset&#34;</span><span class="p">)</span>   <span class="c1">-- Escape 離開</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="n">hl.submap</span><span class="p">(</span><span class="s2">&#34;reset&#34;</span><span class="p">)</span></span></span></code></pre></div><p>進入 resize 模式後，直接按 HJKL（不需要 modifier）就能持續調整大小，按 Escape 回到正常模式。</p>
<h3 id="媒體鍵與硬體鍵">媒體鍵與硬體鍵</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">-- 音量（鎖屏時也能用、長按連續觸發）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">hl.bindel</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;XF86AudioRaiseVolume&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">hl.bindel</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;XF86AudioLowerVolume&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="n">hl.bindl</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;XF86AudioMute&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">hl.bindl</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;XF86AudioMicMute&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1">-- 亮度</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="n">hl.bindel</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;XF86MonBrightnessUp&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;brightnessctl s 10%+&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="n">hl.bindel</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;XF86MonBrightnessDown&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;brightnessctl s 10%-&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1">-- 媒體播放</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">hl.bindl</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;XF86AudioPlay&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;playerctl play-pause&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="n">hl.bindl</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;XF86AudioNext&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;playerctl next&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="n">hl.bindl</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;XF86AudioPrev&#34;</span><span class="p">,</span> <span class="s2">&#34;exec&#34;</span><span class="p">,</span> <span class="s2">&#34;playerctl previous&#34;</span><span class="p">)</span></span></span></code></pre></div><blockquote>
<p><strong>[需實機測試]</strong> 媒體鍵（XF86Audio*）、亮度鍵（XF86MonBrightness*）、合蓋開關——這些依賴實體硬體送出正確的 keycode。VM 鍵盤通常沒有這些鍵。</p></blockquote>
<h2 id="環境變數">環境變數</h2>
<p>環境變數在 <code>hl.config()</code> 的 <code>env</code> 區段設定，影響 Hyprland 自身和其下執行的應用程式：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">-- ~/.config/hypr/env.lua</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="n">env</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="c1">-- 游標主題</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="s2">&#34;XCURSOR_SIZE, 24&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="s2">&#34;XCURSOR_THEME, Bibata-Modern-Classic&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="s2">&#34;HYPRCURSOR_SIZE, 24&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="s2">&#34;HYPRCURSOR_THEME, Bibata-Modern-Classic&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="c1">-- Qt 應用程式</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="s2">&#34;QT_AUTO_SCREEN_SCALE_FACTOR, 1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="s2">&#34;QT_QPA_PLATFORM, wayland;xcb&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="s2">&#34;QT_QPA_PLATFORMTHEME, qt5ct&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="s2">&#34;QT_WAYLAND_DISABLE_WINDOWDECORATION, 1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="c1">-- GTK 應用程式</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="s2">&#34;GDK_BACKEND, wayland,x11,*&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="c1">-- XDG session</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="s2">&#34;XDG_CURRENT_DESKTOP, Hyprland&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">        <span class="s2">&#34;XDG_SESSION_TYPE, wayland&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">        <span class="s2">&#34;XDG_SESSION_DESKTOP, Hyprland&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="c1">-- Electron 應用程式（VS Code, Discord 等）</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="s2">&#34;ELECTRON_OZONE_PLATFORM_HINT, auto&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl">        <span class="c1">-- Firefox</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="s2">&#34;MOZ_ENABLE_WAYLAND, 1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><h3 id="nvidia-專用環境變數">NVIDIA 專用環境變數</h3>
<p>如果使用 NVIDIA 顯卡，需要額外設定（AMD 和 Intel 不需要）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">-- 只在 NVIDIA 機器上加這些</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="n">env</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="s2">&#34;LIBVA_DRIVER_NAME, nvidia&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="s2">&#34;GBM_BACKEND, nvidia-drm&#34;</span><span class="p">,</span>             <span class="c1">-- Firefox 若崩潰就移除這行</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="s2">&#34;__GLX_VENDOR_LIBRARY_NAME, nvidia&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="s2">&#34;NVD_BACKEND, direct&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">cursor</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="n">no_hardware_cursors</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>             <span class="c1">-- NVIDIA 常見的游標問題修正</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="n">allow_dumb_copy</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><blockquote>
<p><strong>[VM 不適用]</strong> NVIDIA 環境變數和驅動設定在 VM 裡無意義——VM 使用 virtio-gpu 或軟體渲染。這些設定只在實體 NVIDIA 機器上測試。</p></blockquote>
<h3 id="vm-專用環境變數">VM 專用環境變數</h3>
<p>在 VM（UTM/QEMU）裡跑 Hyprland 需要額外的回退設定：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">-- 只在 VM 裡加，實機要移除</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="n">env</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">        <span class="s2">&#34;WLR_RENDERER_ALLOW_SOFTWARE, 1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">        <span class="s2">&#34;LIBGL_ALWAYS_SOFTWARE, 1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">        <span class="s2">&#34;WLR_NO_HARDWARE_CURSORS, 1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><blockquote>
<p><strong>[已驗證]</strong> Hyprland 0.55（Aquamarine 渲染後端）+ UTM virtio-gpu-gl-pci 實測：使用 GPU 加速時不需要 <code>WLR_RENDERER</code> 或 <code>LIBGL_ALWAYS_SOFTWARE</code>，Hyprland 自動走 VirGL/Venus 硬體路徑。<code>WLR_NO_HARDWARE_CURSORS</code> 仍需要（virtio-gpu 不支援硬體 cursor）。完整 VM 設定見 <a href="/blog/linux/dotfile/05-hyprland-config/hyprland-vm-setup/" data-link-title="Hyprland VM 環境設定與測試矩陣" data-link-desc="要在 VM 裡測試 Hyprland 配置、或判斷某個設定該在 VM 還是實機驗證時回來讀">VM 環境設定與測試矩陣</a>。</p></blockquote>
]]></content:encoded></item><item><title>Workspace、Window Rules 與外觀</title><link>https://tarrragon.github.io/blog/linux/dotfile/05-hyprland-config/workspace-rules-appearance/</link><pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/05-hyprland-config/workspace-rules-appearance/</guid><description>&lt;p>本篇的配置範例使用 Lua 語法（Hyprland v0.55+）。Lua 基礎見 &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/lua-scripting-language/" data-link-title="Lua 腳本語言" data-link-desc="在 Hyprland 或 Neovim 配置檔遇到 Lua 語法看不懂時回來讀 — 配置檔需要的最小 Lua 知識">Lua 腳本語言&lt;/a>。&lt;/p>
&lt;h2 id="workspace-設定">Workspace 設定&lt;/h2>
&lt;p>Workspace 是平鋪式桌面的空間管理單位。Hyprland 的 workspace 是動態的——不需要預先定義多少個，按了不存在的 workspace 編號就會自動建立。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1">-- 把特定 workspace 綁定到特定螢幕&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="n">hl.config&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> &lt;span class="n">workspace&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;1, monitor:DP-1, default:true&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;2, monitor:DP-1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;3, monitor:DP-1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;7, monitor:HDMI-A-1, default:true&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;8, monitor:HDMI-A-1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;9, monitor:HDMI-A-1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="p">})&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>常見的使用模式：&lt;/p>
&lt;ul>
&lt;li>Workspace 1-3 放在主螢幕（寫程式用）&lt;/li>
&lt;li>Workspace 7-9 放在副螢幕（瀏覽器、通訊軟體、監控）&lt;/li>
&lt;li>用鍵盤瞬間切換（SUPER + 數字鍵），比 alt-tab 在一堆視窗裡找快&lt;/li>
&lt;/ul>
&lt;h3 id="per-workspace-layout-覆寫">Per-workspace layout 覆寫&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="n">hl.config&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> &lt;span class="n">workspace&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;1, layoutopt:orientation:left&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">-- workspace 1 用左側 master&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;2, layoutopt:orientation:top&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">-- workspace 2 用頂部 master&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="p">})&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>[VM 可測試]&lt;/strong> Workspace 切換、綁定邏輯、per-workspace layout。&lt;br>
&lt;strong>[需實機測試]&lt;/strong> Workspace 綁定到特定實體螢幕的行為。&lt;/p>&lt;/blockquote>
&lt;h2 id="window-rules">Window Rules&lt;/h2>
&lt;p>Window rules 讓特定應用程式在開啟時自動套用設定——指定 workspace、強制浮動、設定大小等。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="n">hl.config&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> &lt;span class="n">windowrule&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> &lt;span class="c1">-- 特定 app 自動送到指定 workspace&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;workspace 8, class:^(firefox)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;workspace 9, class:^(Slack)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="c1">-- 設定面板、對話框等維持浮動（不進平鋪）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;float, class:^(pavucontrol)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;float, class:^(nm-connection-editor)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;float, title:^(Open File)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;float, title:^(Save As)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="c1">-- Picture-in-picture 浮動 + 置頂 + 固定大小&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;float, title:^(Picture-in-Picture)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;pin, title:^(Picture-in-Picture)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;size 480 270, title:^(Picture-in-Picture)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;move 100%-490 50, title:^(Picture-in-Picture)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="c1">-- 視窗透明度（active inactive）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;opacity 0.9, class:^(kitty)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;opacity 0.85 0.75, class:^(Code)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="c1">-- 防止 Electron app 自動最大化&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;suppressevent maximize, class:.*&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="c1">-- XWayland video bridge（螢幕分享用）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;opacity 0.0 override, class:^(xwaylandvideobridge)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;noanim, class:^(xwaylandvideobridge)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;noinitialfocus, class:^(xwaylandvideobridge)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;maxsize 1 1, class:^(xwaylandvideobridge)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;noblur, class:^(xwaylandvideobridge)$&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">&lt;span class="p">})&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="查詢應用程式的-class-和-title">查詢應用程式的 class 和 title&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">hyprctl clients &lt;span class="c1"># 列出所有開啟的視窗（含 class、title、PID 等）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">hyprctl activewindow &lt;span class="c1"># 當前焦點視窗的資訊&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Window rules 用 regex 匹配 &lt;code>class&lt;/code> 和 &lt;code>title&lt;/code>。靜態 rules 匹配的是視窗開啟時的初始值（&lt;code>initialTitle&lt;/code> / &lt;code>initialClass&lt;/code>）。&lt;/p></description><content:encoded><![CDATA[<p>本篇的配置範例使用 Lua 語法（Hyprland v0.55+）。Lua 基礎見 <a href="/blog/linux/dotfile/knowledge-cards/lua-scripting-language/" data-link-title="Lua 腳本語言" data-link-desc="在 Hyprland 或 Neovim 配置檔遇到 Lua 語法看不懂時回來讀 — 配置檔需要的最小 Lua 知識">Lua 腳本語言</a>。</p>
<h2 id="workspace-設定">Workspace 設定</h2>
<p>Workspace 是平鋪式桌面的空間管理單位。Hyprland 的 workspace 是動態的——不需要預先定義多少個，按了不存在的 workspace 編號就會自動建立。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">-- 把特定 workspace 綁定到特定螢幕</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="n">workspace</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="s2">&#34;1, monitor:DP-1, default:true&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="s2">&#34;2, monitor:DP-1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="s2">&#34;3, monitor:DP-1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="s2">&#34;7, monitor:HDMI-A-1, default:true&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="s2">&#34;8, monitor:HDMI-A-1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="s2">&#34;9, monitor:HDMI-A-1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><p>常見的使用模式：</p>
<ul>
<li>Workspace 1-3 放在主螢幕（寫程式用）</li>
<li>Workspace 7-9 放在副螢幕（瀏覽器、通訊軟體、監控）</li>
<li>用鍵盤瞬間切換（SUPER + 數字鍵），比 alt-tab 在一堆視窗裡找快</li>
</ul>
<h3 id="per-workspace-layout-覆寫">Per-workspace layout 覆寫</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="n">workspace</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">        <span class="s2">&#34;1, layoutopt:orientation:left&#34;</span><span class="p">,</span>     <span class="c1">-- workspace 1 用左側 master</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">        <span class="s2">&#34;2, layoutopt:orientation:top&#34;</span><span class="p">,</span>      <span class="c1">-- workspace 2 用頂部 master</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><blockquote>
<p><strong>[VM 可測試]</strong> Workspace 切換、綁定邏輯、per-workspace layout。<br>
<strong>[需實機測試]</strong> Workspace 綁定到特定實體螢幕的行為。</p></blockquote>
<h2 id="window-rules">Window Rules</h2>
<p>Window rules 讓特定應用程式在開啟時自動套用設定——指定 workspace、強制浮動、設定大小等。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="n">windowrule</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">        <span class="c1">-- 特定 app 自動送到指定 workspace</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="s2">&#34;workspace 8, class:^(firefox)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="s2">&#34;workspace 9, class:^(Slack)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="c1">-- 設定面板、對話框等維持浮動（不進平鋪）</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="s2">&#34;float, class:^(pavucontrol)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="s2">&#34;float, class:^(nm-connection-editor)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="s2">&#34;float, title:^(Open File)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="s2">&#34;float, title:^(Save As)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="c1">-- Picture-in-picture 浮動 + 置頂 + 固定大小</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="s2">&#34;float, title:^(Picture-in-Picture)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="s2">&#34;pin, title:^(Picture-in-Picture)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="s2">&#34;size 480 270, title:^(Picture-in-Picture)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="s2">&#34;move 100%-490 50, title:^(Picture-in-Picture)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="c1">-- 視窗透明度（active inactive）</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="s2">&#34;opacity 0.9, class:^(kitty)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="s2">&#34;opacity 0.85 0.75, class:^(Code)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl">        <span class="c1">-- 防止 Electron app 自動最大化</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="s2">&#34;suppressevent maximize, class:.*&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="c1">-- XWayland video bridge（螢幕分享用）</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">        <span class="s2">&#34;opacity 0.0 override, class:^(xwaylandvideobridge)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">        <span class="s2">&#34;noanim, class:^(xwaylandvideobridge)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="s2">&#34;noinitialfocus, class:^(xwaylandvideobridge)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="s2">&#34;maxsize 1 1, class:^(xwaylandvideobridge)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">        <span class="s2">&#34;noblur, class:^(xwaylandvideobridge)$&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><h3 id="查詢應用程式的-class-和-title">查詢應用程式的 class 和 title</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">hyprctl clients          <span class="c1"># 列出所有開啟的視窗（含 class、title、PID 等）</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">hyprctl activewindow     <span class="c1"># 當前焦點視窗的資訊</span></span></span></code></pre></div><p>Window rules 用 regex 匹配 <code>class</code> 和 <code>title</code>。靜態 rules 匹配的是視窗開啟時的初始值（<code>initialTitle</code> / <code>initialClass</code>）。</p>
<p>Window rules 是讓平鋪式桌面「不只是把所有東西硬塞格子」的關鍵——識別哪些 app 適合浮動、哪些適合指定位置，需要累積使用經驗。</p>
<blockquote>
<p><strong>[VM 可測試]</strong> Window rules 邏輯、workspace 指派、float 規則。查 class/title 也在 VM 裡能做。</p></blockquote>
<h2 id="layout-配置">Layout 配置</h2>
<h3 id="dwindle">Dwindle</h3>
<p>每個新視窗把當前區域一分為二（螺旋式切分），適合不固定視窗數量的工作流：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="n">dwindle</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">        <span class="n">pseudotile</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>       <span class="c1">-- 允許 app 請求 pseudo-tiling（保留原始大小）</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">        <span class="n">preserve_split</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>   <span class="c1">-- 不自動改變分割方向</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">        <span class="n">force_split</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span>         <span class="c1">-- 0=跟隨滑鼠, 1=永遠左/上, 2=永遠右/下</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">        <span class="n">smart_split</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">        <span class="n">smart_resizing</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><h3 id="master">Master</h3>
<p>一個主區域 + 其餘視窗堆疊在側邊，適合「一個主力視窗 + 多個參考視窗」的模式：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="n">master</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">        <span class="n">new_on_top</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span>       <span class="c1">-- 新視窗放 master 還是 stack</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">        <span class="n">orientation</span> <span class="o">=</span> <span class="s2">&#34;left&#34;</span><span class="p">,</span>     <span class="c1">-- master 區域位置：left / right / top / bottom / center</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">        <span class="n">mfact</span> <span class="o">=</span> <span class="mf">0.55</span><span class="p">,</span>             <span class="c1">-- master 區域佔螢幕的比例</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><p>在 <code>general</code> 裡設定預設 layout：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="n">general</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">        <span class="n">layout</span> <span class="o">=</span> <span class="s2">&#34;dwindle&#34;</span><span class="p">,</span>       <span class="c1">-- 或 &#34;master&#34;</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><blockquote>
<p><strong>[VM 可測試]</strong> Layout 切換和參數調整的行為邏輯。</p></blockquote>
<h2 id="外觀設定">外觀設定</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="n">general</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">        <span class="n">gaps_in</span> <span class="o">=</span> <span class="mi">5</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="n">gaps_out</span> <span class="o">=</span> <span class="mi">10</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="n">border_size</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="p">[</span><span class="s2">&#34;col.active_border&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;rgba(89b4faee) rgba(cba6f7ee) 45deg&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="p">[</span><span class="s2">&#34;col.inactive_border&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;rgba(313244aa)&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">decoration</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="n">rounding</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="n">blur</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">            <span class="n">enabled</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">            <span class="n">size</span> <span class="o">=</span> <span class="mi">5</span><span class="p">,</span>             <span class="c1">-- 模糊半徑（越高越模糊、越吃 GPU）</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">            <span class="n">passes</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span>           <span class="c1">-- 模糊次數（越多越平滑、越重）</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">            <span class="n">vibrancy</span> <span class="o">=</span> <span class="mf">0.17</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">            <span class="n">noise</span> <span class="o">=</span> <span class="mf">0.02</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">            <span class="n">new_optimizations</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="n">shadow</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">            <span class="n">enabled</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">            <span class="n">range</span> <span class="o">=</span> <span class="mi">15</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">            <span class="n">render_power</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span>     <span class="c1">-- 1-4，衰減曲線</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">            <span class="n">color</span> <span class="o">=</span> <span class="s2">&#34;0xee1a1a2e&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl">        <span class="n">dim_inactive</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="n">dim_strength</span> <span class="o">=</span> <span class="mf">0.2</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">
</span></span><span class="line"><span class="ln">31</span><span class="cl">        <span class="n">active_opacity</span> <span class="o">=</span> <span class="mf">1.0</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">        <span class="n">inactive_opacity</span> <span class="o">=</span> <span class="mf">0.95</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><blockquote>
<p><strong>[需實機測試]</strong> blur 的效能影響和視覺品質——這是 Hyprland 最吃 GPU 的功能。VM 裡建議 <code>blur = { enabled = false }</code> 避免卡頓。shadow 和 rounding 在軟體渲染下可以動但會很慢。</p></blockquote>
<h2 id="動畫設定">動畫設定</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">-- 定義 bezier 曲線</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">hl.animation</span><span class="p">(</span><span class="s2">&#34;bezier&#34;</span><span class="p">,</span> <span class="s2">&#34;ease&#34;</span><span class="p">,</span> <span class="mf">0.25</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">,</span> <span class="mf">0.25</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">hl.animation</span><span class="p">(</span><span class="s2">&#34;bezier&#34;</span><span class="p">,</span> <span class="s2">&#34;overshot&#34;</span><span class="p">,</span> <span class="mf">0.05</span><span class="p">,</span> <span class="mf">0.9</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">,</span> <span class="mf">1.05</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1">-- Spring 物理動畫（較新的替代方案）</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="n">hl.animation</span><span class="p">(</span><span class="s2">&#34;spring&#34;</span><span class="p">,</span> <span class="s2">&#34;bouncy&#34;</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>   <span class="c1">-- damping, frequency, speed</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1">-- 套用動畫</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="n">hl.animation</span><span class="p">(</span><span class="s2">&#34;animation&#34;</span><span class="p">,</span> <span class="s2">&#34;windows&#34;</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="s2">&#34;ease&#34;</span><span class="p">,</span> <span class="s2">&#34;slide&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="n">hl.animation</span><span class="p">(</span><span class="s2">&#34;animation&#34;</span><span class="p">,</span> <span class="s2">&#34;windowsOut&#34;</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="s2">&#34;ease&#34;</span><span class="p">,</span> <span class="s2">&#34;popin 80%&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="n">hl.animation</span><span class="p">(</span><span class="s2">&#34;animation&#34;</span><span class="p">,</span> <span class="s2">&#34;fade&#34;</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="s2">&#34;ease&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">hl.animation</span><span class="p">(</span><span class="s2">&#34;animation&#34;</span><span class="p">,</span> <span class="s2">&#34;workspaces&#34;</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="s2">&#34;ease&#34;</span><span class="p">,</span> <span class="s2">&#34;slide&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1">-- 關閉特定動畫</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="n">hl.animation</span><span class="p">(</span><span class="s2">&#34;animation&#34;</span><span class="p">,</span> <span class="s2">&#34;windowsMove&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span></span></span></code></pre></div><p>VM 裡跑 Hyprland 時，建議完全關閉動畫以維持可用的操作速度：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="n">animations</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">        <span class="n">enabled</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><blockquote>
<p><strong>[需實機測試]</strong> 動畫流暢度是 Hyprland 的核心賣點，只有實機能評估。VM 裡的卡頓是 GPU 加速不足造成的，不代表 Hyprland 本身的效能。</p></blockquote>
<h2 id="autostart">Autostart</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="n">exec_once</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">        <span class="c1">-- 桌面元件</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="s2">&#34;waybar&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="s2">&#34;mako&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="s2">&#34;hyprpaper&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="c1">-- 系統服務</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="s2">&#34;/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="s2">&#34;wl-paste --type text --watch cliphist store&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="c1">-- Idle daemon（閒置鎖屏，鎖屏安全模型見 session-lock 卡）</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="s2">&#34;hypridle&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><p><code>exec_once</code> 只在 Hyprland 啟動時跑一次（config reload 不會重複執行）。如果需要每次 reload 都重跑某個指令，用 <code>exec</code>（但多數情況不需要）。</p>
<h2 id="plugin-系統">Plugin 系統</h2>
<p>Hyprland 用 <code>hyprpm</code>（Hyprland Plugin Manager）管理 plugin：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">hyprpm update                                              <span class="c1"># 更新 plugin index</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">hyprpm add https://github.com/hyprwm/hyprland-plugins     <span class="c1"># 加入官方 plugin repo</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">hyprpm <span class="nb">enable</span> hyprexpo                                     <span class="c1"># 啟用 plugin</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">hyprpm disable hyprexpo                                    <span class="c1"># 停用 plugin</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">hyprpm list                                                <span class="c1"># 列出可用 plugin</span></span></span></code></pre></div><table>
  <thead>
      <tr>
          <th>Plugin</th>
          <th>功能</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>hyprexpo</strong></td>
          <td>workspace 鳥瞰（所有 workspace 縮圖一覽）</td>
      </tr>
      <tr>
          <td><strong>hy3</strong></td>
          <td>i3/sway 風格的手動 tiling layout（替代 dwindle）</td>
      </tr>
      <tr>
          <td><strong>hyprspace</strong></td>
          <td>類似 macOS Mission Control 的 workspace 切換動畫</td>
      </tr>
      <tr>
          <td><strong>hyprbars</strong></td>
          <td>視窗標題列（可自訂按鈕）</td>
      </tr>
      <tr>
          <td><strong>hyprtrails</strong></td>
          <td>游標拖尾特效</td>
      </tr>
  </tbody>
</table>
<p>Plugin 的配置寫在 hyprland.lua 裡，是 dotfile 的一部分。</p>
<blockquote>
<p><strong>[VM 可測試]</strong> 不依賴 GPU 的 plugin（hy3、hyprbars）。<br>
<strong>[需實機測試]</strong> 視覺特效類 plugin（hyprexpo、hyprspace、hyprtrails）。</p></blockquote>
<h2 id="dotfile-結構對應">Dotfile 結構對應</h2>
<p>Hyprland 的配置拆成多個 <code>.lua</code> 檔，全部放在同一個 stow package 裡。<code>monitors.lua</code> 是硬體相關的——跨機器搬移時可能要排除或用 template/local 機制處理（見<a href="/blog/linux/dotfile/01-dotfile-management/cross-platform-one-repo/" data-link-title="跨平台共用一個 Repo" data-link-desc="macOS 跟 Linux 要共用同一個 dotfile repo、不想維護兩份時回來讀">跨平台共用一個 Repo</a>）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">~/dotfiles/
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">└── hyprland/
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    └── .config/
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        └── hypr/
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">            ├── hyprland.lua       # 主入口（只有 require 行）
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">            ├── monitors.lua       # 硬體相關、可能排除或 template
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">            ├── keybinds.lua
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">            ├── rules.lua
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">            ├── autostart.lua
</span></span><span class="line"><span class="ln">10</span><span class="cl">            ├── appearance.lua
</span></span><span class="line"><span class="ln">11</span><span class="cl">            └── env.lua</span></span></code></pre></div><h2 id="穩定性與維護的務實面">穩定性與維護的務實面</h2>
<p>Hyprland 的開發節奏快、功能更新激進。v0.55 的 Lua 遷移就是一個典型案例——配置格式整個換掉，舊的 <code>.conf</code> 只會再支援一到兩個版本。配置檔的語法和可用選項會隨版本變動。</p>
<p>應對策略：</p>
<ul>
<li>更新前先看 Hyprland wiki 的 Configuring 頁面和 changelog</li>
<li>dotfile repo 的 commit message 記錄「因應 Hyprland vX.Y 改了什麼設定」</li>
<li>如果用 Arch 的 rolling release，<code>pacman -Syu</code> 前先確認 Hyprland 是否有 breaking change（Arch 社群通常會在論壇預警）</li>
<li>官方提供遷移工具（如 <code>hyprlang2lua</code>），格式變更時優先使用</li>
</ul>
<p>這是<a href="/blog/linux/dotfile/04-window-management/" data-link-title="模組四：視窗管理與平鋪式工作流" data-link-desc="同時開多個視窗時的排列策略 — 手動貼齊跟自動平鋪的差距在哪、macOS 和 Linux 各有哪些工具、多螢幕怎麼處理、什麼情境值得從浮動切換到平鋪">視窗管理與平鋪式工作流</a>提過的代價——把日常桌面建立在高速移動的專案上，持續的配置維護是實際成本。</p>
<h2 id="vm-與實機測試對照">VM 與實機測試對照</h2>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>VM 可測試</th>
          <th>需實機測試</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>配置語法 / 結構</td>
          <td>可</td>
          <td></td>
      </tr>
      <tr>
          <td>Keybind 設計</td>
          <td>可</td>
          <td></td>
      </tr>
      <tr>
          <td>Window rules 邏輯</td>
          <td>可</td>
          <td></td>
      </tr>
      <tr>
          <td>Workspace 切換</td>
          <td>可</td>
          <td></td>
      </tr>
      <tr>
          <td>Layout 參數</td>
          <td>可</td>
          <td></td>
      </tr>
      <tr>
          <td>Autostart 順序</td>
          <td>可</td>
          <td></td>
      </tr>
      <tr>
          <td>Plugin 配置</td>
          <td>部分</td>
          <td>視覺類</td>
      </tr>
      <tr>
          <td>動畫流暢度</td>
          <td></td>
          <td>必要</td>
      </tr>
      <tr>
          <td>Blur 效能 / 品質</td>
          <td></td>
          <td>必要</td>
      </tr>
      <tr>
          <td>多螢幕排列</td>
          <td></td>
          <td>必要</td>
      </tr>
      <tr>
          <td>HiDPI 縮放</td>
          <td></td>
          <td>必要</td>
      </tr>
      <tr>
          <td>觸控板 / 手勢</td>
          <td></td>
          <td>必要</td>
      </tr>
      <tr>
          <td>媒體鍵 / 亮度鍵</td>
          <td></td>
          <td>必要</td>
      </tr>
      <tr>
          <td>NVIDIA 驅動設定</td>
          <td></td>
          <td>必要</td>
      </tr>
      <tr>
          <td>螢幕分享</td>
          <td></td>
          <td>必要</td>
      </tr>
      <tr>
          <td>休眠 / 喚醒</td>
          <td></td>
          <td>必要</td>
      </tr>
      <tr>
          <td>合蓋行為</td>
          <td></td>
          <td>必要</td>
      </tr>
  </tbody>
</table>
]]></content:encoded></item><item><title>Hyprland VM 環境設定與測試矩陣</title><link>https://tarrragon.github.io/blog/linux/dotfile/05-hyprland-config/hyprland-vm-setup/</link><pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/05-hyprland-config/hyprland-vm-setup/</guid><description>&lt;p>VM 是 Hyprland 配置的演練場——用來驗證「配置邏輯對不對」，不是用來體驗「跑起來順不順」。GPU 加速在 VM 中受限，動畫和模糊效果會嚴重降級或無法使用，但配置檔語法、keybind 設計、window rules、workspace 邏輯都能在 VM 中完整測試。&lt;/p>
&lt;h2 id="utm-on-apple-silicon-設定">UTM on Apple Silicon 設定&lt;/h2>
&lt;p>Apple Silicon Mac 用 UTM（基於 QEMU）跑 ARM64 Linux VM：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>CPU&lt;/strong>：UTM 使用 Apple Hypervisor.framework，ARM64 guest 接近原生速度&lt;/li>
&lt;li>&lt;strong>GPU&lt;/strong>：使用 &lt;code>virtio-gpu-gl-pci&lt;/code>（UTM v4.1+ 新建 Linux VM 的預設）。UTM v5.0.0+ 的 GitHub release 版支援 Venus driver（guest Mesa → host MoltenVK → Apple Metal 的 Vulkan 轉送路徑），這是目前最好的 GPU 加速方案&lt;/li>
&lt;li>&lt;strong>Linux ISO&lt;/strong>：Arch Linux ARM（archlinuxarm.org）或 Fedora aarch64&lt;/li>
&lt;li>&lt;strong>建議配置&lt;/strong>：4 CPU cores、4GB+ RAM、40GB+ disk&lt;/li>
&lt;/ul>
&lt;h3 id="utm-建-vm-的注意事項">UTM 建 VM 的注意事項&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>第一頁選 Virtualize，不是 Emulate&lt;/strong>——同架構（Apple Silicon 跑 ARM64 guest）兩條都是 QEMU，差在 Virtualize 走 hvf 硬體虛擬化（CPU 接近原生）、Emulate 走 TCG 純軟體模擬（CPU 慢一個數量級；實測 C++ 大型編譯一小時只跑 1/3）。Emulate 只在跨架構（ARM Mac 跑 x86_64 guest）才需要。判別現有 VM：guest 裡 &lt;code>lscpu&lt;/code> 的 Model name 是 &lt;code>-&lt;/code> 為直通、顯示具體型號（如 Cortex-A72）為模擬&lt;/li>
&lt;li>選 「Linux」 虛擬機類型，不是 「Other」&lt;/li>
&lt;li>Display Card 選 &lt;code>virtio-gpu-gl-pci&lt;/code>（有 3D 加速），不是 &lt;code>virtio-gpu-pci&lt;/code>（無加速）；Emulate 精靈預設給無加速的 &lt;code>virtio-gpu-pci&lt;/code>、Virtualize 精靈通常直接給對&lt;/li>
&lt;li>&lt;strong>VM 視窗可能停在序列視圖、圖形顯示是另一個視圖&lt;/strong>——Virtualize 精靈預設多附一個序列裝置，UTM 視窗開機後可能顯示的是序列 console（文字登入、guest 裡 &lt;code>who&lt;/code> 顯示登入在 &lt;code>pts/0&lt;/code>），跟 virtio-gpu 的圖形輸出是兩個獨立視圖。切換：VM 視窗工具列的顯示器下拉選單 → 選 &lt;code>Display 1 (virtio-gpu)&lt;/code>。判讀圖形裝置本身有沒有掛上看 guest 的 &lt;code>ls /dev/dri/&lt;/code>（有 &lt;code>card0&lt;/code> = 裝置在、只是視窗看錯視圖）。不想每次切就到 VM 設定移除序列裝置。compositor 要在圖形視圖那側的 VT 上啟動、序列 console 起不了 Hyprland&lt;/li>
&lt;li>如果用 App Store 版的 UTM（不含 Venus），只有基本的 virtio-gpu-gl 加速&lt;/li>
&lt;li>GitHub release 版的 UTM 支援 Venus/MoltenVK，效能更好但仍不及裸金屬&lt;/li>
&lt;li>&lt;strong>修飾鍵：Mac 的 ⌘ 對應 guest 的 &lt;code>SUPER&lt;/code>，但 macOS 會先攔截部分 ⌘ 組合&lt;/strong>——Hyprland 的 keybind 幾乎都以 &lt;code>SUPER&lt;/code>（Meta）當主修飾鍵（見 &lt;a href="../hyprland-core-config/">核心配置的修飾鍵段&lt;/a>），而 UTM 裡 Mac 的 Command ⌘ 通常就是那顆 &lt;code>SUPER&lt;/code>。問題是 macOS 自己會先吃掉某些 ⌘ 組合（⌘+Q 結束 app、⌘+Space Spotlight…），VM 收不到。判讀：&lt;code>SUPER&lt;/code> 綁定沒反應、但焦點視窗打字正常，多半是宿主層攔截、不是 Hyprland 配置錯。解法：先確認 VM 視窗有 focus；在 UTM 的鍵盤/輸入設定開「把系統快捷鍵送進 VM（capture input）」讓 ⌘ 組合進 guest。臨時繞過：需要重載配置這類動作，直接在已開的終端機下指令（如 &lt;code>source&lt;/code> / &lt;code>hyprctl reload&lt;/code>），不必卡在 ⌘ 鍵上&lt;/li>
&lt;/ul>
&lt;h2 id="vm-必要環境變數">VM 必要環境變數&lt;/h2>
&lt;p>在 Hyprland 配置裡加入以下環境變數（只在 VM 中使用，實機要移除）：&lt;/p></description><content:encoded><![CDATA[<p>VM 是 Hyprland 配置的演練場——用來驗證「配置邏輯對不對」，不是用來體驗「跑起來順不順」。GPU 加速在 VM 中受限，動畫和模糊效果會嚴重降級或無法使用，但配置檔語法、keybind 設計、window rules、workspace 邏輯都能在 VM 中完整測試。</p>
<h2 id="utm-on-apple-silicon-設定">UTM on Apple Silicon 設定</h2>
<p>Apple Silicon Mac 用 UTM（基於 QEMU）跑 ARM64 Linux VM：</p>
<ul>
<li><strong>CPU</strong>：UTM 使用 Apple Hypervisor.framework，ARM64 guest 接近原生速度</li>
<li><strong>GPU</strong>：使用 <code>virtio-gpu-gl-pci</code>（UTM v4.1+ 新建 Linux VM 的預設）。UTM v5.0.0+ 的 GitHub release 版支援 Venus driver（guest Mesa → host MoltenVK → Apple Metal 的 Vulkan 轉送路徑），這是目前最好的 GPU 加速方案</li>
<li><strong>Linux ISO</strong>：Arch Linux ARM（archlinuxarm.org）或 Fedora aarch64</li>
<li><strong>建議配置</strong>：4 CPU cores、4GB+ RAM、40GB+ disk</li>
</ul>
<h3 id="utm-建-vm-的注意事項">UTM 建 VM 的注意事項</h3>
<ul>
<li><strong>第一頁選 Virtualize，不是 Emulate</strong>——同架構（Apple Silicon 跑 ARM64 guest）兩條都是 QEMU，差在 Virtualize 走 hvf 硬體虛擬化（CPU 接近原生）、Emulate 走 TCG 純軟體模擬（CPU 慢一個數量級；實測 C++ 大型編譯一小時只跑 1/3）。Emulate 只在跨架構（ARM Mac 跑 x86_64 guest）才需要。判別現有 VM：guest 裡 <code>lscpu</code> 的 Model name 是 <code>-</code> 為直通、顯示具體型號（如 Cortex-A72）為模擬</li>
<li>選 「Linux」 虛擬機類型，不是 「Other」</li>
<li>Display Card 選 <code>virtio-gpu-gl-pci</code>（有 3D 加速），不是 <code>virtio-gpu-pci</code>（無加速）；Emulate 精靈預設給無加速的 <code>virtio-gpu-pci</code>、Virtualize 精靈通常直接給對</li>
<li><strong>VM 視窗可能停在序列視圖、圖形顯示是另一個視圖</strong>——Virtualize 精靈預設多附一個序列裝置，UTM 視窗開機後可能顯示的是序列 console（文字登入、guest 裡 <code>who</code> 顯示登入在 <code>pts/0</code>），跟 virtio-gpu 的圖形輸出是兩個獨立視圖。切換：VM 視窗工具列的顯示器下拉選單 → 選 <code>Display 1 (virtio-gpu)</code>。判讀圖形裝置本身有沒有掛上看 guest 的 <code>ls /dev/dri/</code>（有 <code>card0</code> = 裝置在、只是視窗看錯視圖）。不想每次切就到 VM 設定移除序列裝置。compositor 要在圖形視圖那側的 VT 上啟動、序列 console 起不了 Hyprland</li>
<li>如果用 App Store 版的 UTM（不含 Venus），只有基本的 virtio-gpu-gl 加速</li>
<li>GitHub release 版的 UTM 支援 Venus/MoltenVK，效能更好但仍不及裸金屬</li>
<li><strong>修飾鍵：Mac 的 ⌘ 對應 guest 的 <code>SUPER</code>，但 macOS 會先攔截部分 ⌘ 組合</strong>——Hyprland 的 keybind 幾乎都以 <code>SUPER</code>（Meta）當主修飾鍵（見 <a href="../hyprland-core-config/">核心配置的修飾鍵段</a>），而 UTM 裡 Mac 的 Command ⌘ 通常就是那顆 <code>SUPER</code>。問題是 macOS 自己會先吃掉某些 ⌘ 組合（⌘+Q 結束 app、⌘+Space Spotlight…），VM 收不到。判讀：<code>SUPER</code> 綁定沒反應、但焦點視窗打字正常，多半是宿主層攔截、不是 Hyprland 配置錯。解法：先確認 VM 視窗有 focus；在 UTM 的鍵盤/輸入設定開「把系統快捷鍵送進 VM（capture input）」讓 ⌘ 組合進 guest。臨時繞過：需要重載配置這類動作，直接在已開的終端機下指令（如 <code>source</code> / <code>hyprctl reload</code>），不必卡在 ⌘ 鍵上</li>
</ul>
<h2 id="vm-必要環境變數">VM 必要環境變數</h2>
<p>在 Hyprland 配置裡加入以下環境變數（只在 VM 中使用，實機要移除）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">-- VM-only environment variables</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="n">env</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="s2">&#34;WLR_RENDERER_ALLOW_SOFTWARE, 1&#34;</span><span class="p">,</span>  <span class="c1">-- 允許軟體渲染 fallback</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="s2">&#34;WLR_NO_HARDWARE_CURSORS, 1&#34;</span><span class="p">,</span>      <span class="c1">-- 停用硬體 cursor（VM 常見問題）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="s2">&#34;LIBGL_ALWAYS_SOFTWARE, 1&#34;</span><span class="p">,</span>        <span class="c1">-- 強制 Mesa 軟體渲染</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>如果上述仍無法啟動（virtio-gpu vGPU passthrough 的情況）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">env</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="s2">&#34;AQ_NO_KMS_REQUIREMENT, 1&#34;</span><span class="p">,</span>       <span class="c1">-- 繞過 KMS 需求</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="s2">&#34;WLR_RENDERER, pixman&#34;</span><span class="p">,</span>            <span class="c1">-- 強制 pixman 軟體 renderer</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><blockquote>
<p><strong>[已驗證]</strong> Hyprland 0.55（Aquamarine）+ UTM virtio-gpu-gl-pci 實測：GPU 加速模式下 Hyprland 直接走 VirGL/Venus，不需要 <code>WLR_RENDERER</code> 或 <code>WLR_RENDERER_ALLOW_SOFTWARE</code>。<code>AQ_NO_KMS_REQUIREMENT</code> 仍有效。軟體渲染 fallback 路徑（<code>WLR_RENDERER=pixman</code>）未測試——有 GPU 加速時不需要走這條。</p></blockquote>
<h2 id="vm-中應該關閉的效果">VM 中應該關閉的效果</h2>
<p>軟體渲染下，視覺效果是最大的效能殺手。建議在 VM 配置中停用：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="n">hl.config</span><span class="p">({</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="n">decoration</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">        <span class="n">blur</span> <span class="o">=</span> <span class="p">{</span> <span class="n">enabled</span> <span class="o">=</span> <span class="kc">false</span> <span class="p">},</span>     <span class="c1">-- 模糊是 GPU 最重的效果</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="n">shadow</span> <span class="o">=</span> <span class="p">{</span> <span class="n">enabled</span> <span class="o">=</span> <span class="kc">false</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="n">rounding</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="n">animations</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="n">enabled</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span>                <span class="c1">-- 或設定極簡動畫</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="p">})</span></span></span></code></pre></div><p>這些效果關閉後，基本的平鋪操作（切換視窗、移動 workspace、開關 app）在 VM 中應該足夠流暢。</p>
<h2 id="效能預期">效能預期</h2>
<table>
  <thead>
      <tr>
          <th>功能</th>
          <th>軟體渲染</th>
          <th>virtio-gpu-gl</th>
          <th>裸金屬（實機）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>基本平鋪操作</td>
          <td>可用</td>
          <td>順暢</td>
          <td>順暢</td>
      </tr>
      <tr>
          <td>視窗動畫</td>
          <td>卡頓明顯</td>
          <td>勉強可接受</td>
          <td>流暢</td>
      </tr>
      <tr>
          <td>模糊/透明</td>
          <td>無法使用</td>
          <td>卡頓</td>
          <td>流暢</td>
      </tr>
      <tr>
          <td>Waybar + Wofi</td>
          <td>正常</td>
          <td>正常</td>
          <td>正常</td>
      </tr>
      <tr>
          <td>多 Workspace 切換</td>
          <td>正常</td>
          <td>正常</td>
          <td>正常</td>
      </tr>
      <tr>
          <td>Firefox 瀏覽</td>
          <td>明顯變慢</td>
          <td>可用</td>
          <td>正常</td>
      </tr>
  </tbody>
</table>
<p>VM 的價值在於驗證配置邏輯，不在於評估視覺體驗。如果在 VM 裡覺得「卡」，不代表 Hyprland 本身慢——多數情況是 VM 圖形加速的限制。</p>
<h2 id="sway-作為-vm-初步驗證工具">Sway 作為 VM 初步驗證工具</h2>
<p>如果 VM 中 Hyprland 跑得太吃力，可以先用 Sway 驗證 VM 的 Wayland 圖形棧是否正常：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo pacman -S sway foot
</span></span><span class="line"><span class="ln">2</span><span class="cl">sway</span></span></code></pre></div><p>Sway 比 Hyprland 輕量（基於 wlroots、沒有華麗動畫），如果 Sway 能跑，代表 VM 的 Wayland 環境是正常的，Hyprland 的問題只是效能不夠。如果連 Sway 都跑不動，要回去檢查 VM 的 GPU 設定。</p>
<h2 id="vm-vs-實機測試矩陣">VM vs 實機測試矩陣</h2>
<h3 id="vm-中可完整驗證">VM 中可完整驗證</h3>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>配置檔語法</td>
          <td>Lua config 是否解析正確、require 拆分是否正常</td>
      </tr>
      <tr>
          <td>Keybind 設計</td>
          <td>快捷鍵邏輯、submap、modifier 組合</td>
      </tr>
      <tr>
          <td>Window rules</td>
          <td>float / workspace assignment / opacity 規則是否生效</td>
      </tr>
      <tr>
          <td>Workspace 切換</td>
          <td>workspace 編號、切換邏輯</td>
      </tr>
      <tr>
          <td>Layout 選擇</td>
          <td>dwindle vs master 的行為差異</td>
      </tr>
      <tr>
          <td>Waybar 模組配置</td>
          <td>JSON config + CSS styling 是否正確顯示</td>
      </tr>
      <tr>
          <td>Wofi/Rofi 主題</td>
          <td>啟動器的功能和外觀設定</td>
      </tr>
      <tr>
          <td>Mako 通知樣式</td>
          <td>通知的位置、配色、timeout</td>
      </tr>
      <tr>
          <td>Hyprlock 佈局</td>
          <td>鎖屏的輸入框位置和文字配置</td>
      </tr>
      <tr>
          <td>Autostart 順序</td>
          <td>exec-once 的程式是否正確啟動</td>
      </tr>
      <tr>
          <td>環境變數</td>
          <td>XDG、Qt、GTK 等環境變數是否正確設定</td>
      </tr>
      <tr>
          <td>Stow 部署</td>
          <td>dotfile repo 的 stow 是否正確建立 symlink</td>
      </tr>
      <tr>
          <td>Bootstrap script</td>
          <td>install.sh 的完整流程（安裝套件 + deploy 配置）</td>
      </tr>
      <tr>
          <td>Caelestia CLI 指令</td>
          <td><code>caelestia shell</code>、<code>caelestia scheme</code> 等指令是否可執行</td>
      </tr>
  </tbody>
</table>
<h3 id="需要實機測試">需要實機測試</h3>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>為什麼 VM 不行</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>多螢幕配置</td>
          <td>VM 通常只有一個虛擬顯示器</td>
      </tr>
      <tr>
          <td>HiDPI / fractional scaling</td>
          <td>虛擬顯示器不模擬真實解析度行為</td>
      </tr>
      <tr>
          <td>VRR / Adaptive Sync</td>
          <td>需要支援 VRR 的真實螢幕</td>
      </tr>
      <tr>
          <td>動畫流暢度</td>
          <td>VM 的 GPU 加速不足以評估真實效能</td>
      </tr>
      <tr>
          <td>模糊效果品質</td>
          <td>軟體渲染下模糊不可用或品質差</td>
      </tr>
      <tr>
          <td>觸控板 / 手勢</td>
          <td>VM 沒有觸控板裝置</td>
      </tr>
      <tr>
          <td>媒體鍵 / 亮度鍵</td>
          <td>需要實體鍵盤上的 XF86 keycodes</td>
      </tr>
      <tr>
          <td>NVIDIA 驅動設定</td>
          <td>VM 不走 NVIDIA 驅動，所有 NVIDIA 配置無法測試</td>
      </tr>
      <tr>
          <td>Screen sharing</td>
          <td>PipeWire + portal 的完整鏈路在 VM 中測試無意義</td>
      </tr>
      <tr>
          <td>Suspend / Resume</td>
          <td>虛擬機的 suspend 行為跟實機不同</td>
      </tr>
      <tr>
          <td>硬體 cursor 渲染</td>
          <td>VM 用軟體 cursor，無法測試硬體 cursor 問題</td>
      </tr>
      <tr>
          <td>藍牙 / WiFi 整合</td>
          <td>需要實際硬體</td>
      </tr>
      <tr>
          <td>電池 / 電源管理</td>
          <td>筆電專屬功能</td>
      </tr>
      <tr>
          <td>日常使用效能</td>
          <td>只有在實機跑一段時間才能評估「能不能當主力」</td>
      </tr>
  </tbody>
</table>
<h2 id="務實的-vm-使用策略">務實的 VM 使用策略</h2>
<p>VM 階段的目標是「把配置寫好、驗證邏輯、確認 bootstrap script 能跑」，不是「體驗 Hyprland 好不好用」。具體做法：</p>
<ol>
<li>在 VM 中完成 Arch Linux 安裝 + Hyprland 套件安裝（怎麼把那台 Linux 從 ISO 裝起來、安裝程式選項怎麼判讀、裝完怎麼驗工具與連入，見 <a href="/blog/linux/install/" data-link-title="Linux 安裝與機器初始化" data-link-desc="在 VM 或新機器從零裝好 Linux、判讀安裝程式選項、驗證最小系統、或要從外部連入跑 bootstrap 時回來讀">Linux 安裝與機器初始化</a>）</li>
<li>關閉所有視覺效果（blur / animation / shadow）</li>
<li>寫好完整的 Hyprland 配置（keybind / rules / workspace / autostart）</li>
<li>寫好 waybar / wofi / mako 配置</li>
<li>測試 stow 部署流程（從 dotfile repo clone → stow → 配置生效）</li>
<li>測試 bootstrap script（install.sh 從零到完整桌面）</li>
<li>把驗證過的配置 commit 進 dotfile repo</li>
</ol>
<p>到實機時，clone dotfile repo → 跑 install.sh → 補上硬體相關設定（monitor、GPU 驅動、觸控板）→ 打開視覺效果。VM 階段的工作在實機上幾乎不用重做。</p>
]]></content:encoded></item></channel></rss>