<?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>Waybar on Tarragon</title><link>https://tarrragon.github.io/blog/tags/waybar/</link><description>Recent content in Waybar on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Wed, 01 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/waybar/index.xml" rel="self" type="application/rss+xml"/><item><title>桌面 Shell 元件：狀態列、啟動器與通知</title><link>https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/desktop-shell-components/</link><pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/desktop-shell-components/</guid><description>&lt;p>完整桌面環境（GNOME、KDE）把這些元件整合在一起出貨。平鋪式 WM 的桌面是拼裝的——每個位置自己選工具：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>功能&lt;/th>
 &lt;th>常見工具&lt;/th>
 &lt;th>配置格式&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>狀態列&lt;/td>
 &lt;td>Waybar, Eww, AGS&lt;/td>
 &lt;td>JSON/JSONC, Yuck, JS&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>啟動器&lt;/td>
 &lt;td>Wofi, Rofi (wayland), Fuzzel&lt;/td>
 &lt;td>CSS + 設定檔&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>通知&lt;/td>
 &lt;td>Mako, Dunst, SwayNC&lt;/td>
 &lt;td>INI/TOML&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>鎖屏&lt;/td>
 &lt;td>Hyprlock, Swaylock&lt;/td>
 &lt;td>自定義格式&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>桌布&lt;/td>
 &lt;td>Hyprpaper, Swww, Mpvpaper&lt;/td>
 &lt;td>自定義格式&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>剪貼簿&lt;/td>
 &lt;td>wl-clipboard + Cliphist&lt;/td>
 &lt;td>CLI&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>螢幕截圖&lt;/td>
 &lt;td>Grimblast, Grim + Slurp&lt;/td>
 &lt;td>CLI&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Caelestia 這類「desktop shell 專案」做的就是把上述元件統一設計、統一配色、統一出貨，省去自己一個個挑的功夫。它用的是 Quickshell（QML 框架）把所有元件包成一套風格一致的桌面。本模組教的是自己組裝的方式——理解各元件的配置，之後要用 Caelestia 或自己拼都能做。&lt;/p>
&lt;h2 id="waybar狀態列">Waybar：狀態列&lt;/h2>
&lt;p>Waybar 是 Hyprland 桌面最常用的狀態列。配置在 &lt;code>~/.config/waybar/&lt;/code>，分兩個檔案：&lt;code>config.jsonc&lt;/code>（結構和模組）和 &lt;code>style.css&lt;/code>（外觀）。&lt;/p>
&lt;h3 id="結構配置">結構配置&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-jsonc" data-lang="jsonc">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1">// ~/.config/waybar/config.jsonc
&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">&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="nt">&amp;#34;layer&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;top&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="nt">&amp;#34;position&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;top&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="nt">&amp;#34;height&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">36&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="nt">&amp;#34;spacing&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">4&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>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 左中右三區塊各放哪些模組
&lt;/span>&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 class="nt">&amp;#34;modules-left&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;hyprland/workspaces&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;hyprland/window&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="nt">&amp;#34;modules-center&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;clock&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="nt">&amp;#34;modules-right&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;pulseaudio&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;network&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;cpu&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;memory&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;battery&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;tray&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">// 各模組設定
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nt">&amp;#34;hyprland/workspaces&amp;#34;&lt;/span>&lt;span class="p">:&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="nt">&amp;#34;format&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;{id}&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="nt">&amp;#34;on-click&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;activate&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="nt">&amp;#34;clock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;format&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;{:%H:%M}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;format-alt&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;{:%Y-%m-%d %H:%M}&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="nt">&amp;#34;tooltip-format&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;tt&amp;gt;{calendar}&amp;lt;/tt&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;battery&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;format&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;{capacity}% {icon}&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 class="nt">&amp;#34;format-icons&amp;#34;&lt;/span>&lt;span class="p">:&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;&amp;#34;&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;&amp;#34;&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>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;states&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;warning&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">30&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="nt">&amp;#34;critical&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">15&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &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="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="nt">&amp;#34;network&amp;#34;&lt;/span>&lt;span class="p">:&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="nt">&amp;#34;format-wifi&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;{essid} ({signalStrength}%)&amp;#34;&lt;/span>&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="nt">&amp;#34;format-ethernet&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;{ifname}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;format-disconnected&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Disconnected&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;pulseaudio&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;format&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;{volume}%&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl"> &lt;span class="nt">&amp;#34;on-click&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;pavucontrol&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&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>format&lt;/code> 欄位裡的 icon 字元來自 Nerd Font——&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/03-terminal-ecosystem/" data-link-title="模組三：終端機與編輯器" data-link-desc="終端機相關工具的配置檔散落在不同位置、不確定哪些該進 dotfile repo 時回來讀">終端機與編輯器&lt;/a>提到的字型安裝是這裡正常顯示的前提。&lt;/p>
&lt;h3 id="外觀-css">外觀 CSS&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-css" data-lang="css">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c">/* ~/.config/waybar/style.css */&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="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="k">font-family&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;MesloLGS Nerd Font&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">monospace&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="k">font-size&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">13&lt;/span>&lt;span class="kt">px&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="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="nt">window&lt;/span>&lt;span class="p">#&lt;/span>&lt;span class="nn">waybar&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="k">background-color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">rgba&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">30&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">30&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">46&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">0.85&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="k">color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#cdd6f4&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="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="p">#&lt;/span>&lt;span class="nn">workspaces&lt;/span> &lt;span class="nt">button&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 class="k">padding&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="kt">px&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="k">color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#6c7086&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="k">border-radius&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">6&lt;/span>&lt;span class="kt">px&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="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="p">#&lt;/span>&lt;span class="nn">workspaces&lt;/span> &lt;span class="nt">button&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nc">active&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="k">color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#cdd6f4&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="k">background&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">rgba&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">137&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">180&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">250&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">0.2&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 class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="p">#&lt;/span>&lt;span class="nn">clock&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="p">#&lt;/span>&lt;span class="nn">battery&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="p">#&lt;/span>&lt;span class="nn">network&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="p">#&lt;/span>&lt;span class="nn">pulseaudio&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 class="k">padding&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="kt">px&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">&lt;span class="p">#&lt;/span>&lt;span class="nn">battery&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nc">warning&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="k">color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#f9e2af&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="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">
&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 class="nn">battery&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nc">critical&lt;/span> &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="k">color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#f38ba8&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>CSS 裡的色碼（&lt;code>#cdd6f4&lt;/code>、&lt;code>#89b4fa&lt;/code>、&lt;code>#f38ba8&lt;/code>）來自配色方案（這個範例用的是 Catppuccin Mocha）。統一使用同一套色碼是 rice 視覺協調的基礎。&lt;/p>
&lt;p>Config 裡的字族名必須跟系統實際安裝的字族逐字相符。Nerd Font 的圖示落在專屬碼位範圍，只有對應的那支字帶這些 glyph——指定一個沒裝的字族名，文字排版引擎找不到 glyph 就會顯示豆腐方塊。確認實裝字族名的方式：&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">fc-list &lt;span class="p">|&lt;/span> grep -i meslo
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1"># MesloLGSNerdFont-Regular.ttf: &amp;#34;MesloLGS Nerd Font&amp;#34;:style=Regular&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>引號內的字串是 config 該填的字族名。&lt;/p>
&lt;p>同一份 Waybar config 能同時服務筆電、桌機與 VM，靠的是模組對缺少硬體的自動退化：&lt;code>battery&lt;/code> 在沒有電池的機器直接隱藏該模組、不報錯也不留空位；&lt;code>pulseaudio&lt;/code> 在沒有音訊服務時顯示為空；&lt;code>network&lt;/code> 顯示當下實際在用的介面。不必為不同機器維護多份 config——把可能用到的模組都列上，用不到的那台自己消失。&lt;/p></description><content:encoded><![CDATA[<p>完整桌面環境（GNOME、KDE）把這些元件整合在一起出貨。平鋪式 WM 的桌面是拼裝的——每個位置自己選工具：</p>
<table>
  <thead>
      <tr>
          <th>功能</th>
          <th>常見工具</th>
          <th>配置格式</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>狀態列</td>
          <td>Waybar, Eww, AGS</td>
          <td>JSON/JSONC, Yuck, JS</td>
      </tr>
      <tr>
          <td>啟動器</td>
          <td>Wofi, Rofi (wayland), Fuzzel</td>
          <td>CSS + 設定檔</td>
      </tr>
      <tr>
          <td>通知</td>
          <td>Mako, Dunst, SwayNC</td>
          <td>INI/TOML</td>
      </tr>
      <tr>
          <td>鎖屏</td>
          <td>Hyprlock, Swaylock</td>
          <td>自定義格式</td>
      </tr>
      <tr>
          <td>桌布</td>
          <td>Hyprpaper, Swww, Mpvpaper</td>
          <td>自定義格式</td>
      </tr>
      <tr>
          <td>剪貼簿</td>
          <td>wl-clipboard + Cliphist</td>
          <td>CLI</td>
      </tr>
      <tr>
          <td>螢幕截圖</td>
          <td>Grimblast, Grim + Slurp</td>
          <td>CLI</td>
      </tr>
  </tbody>
</table>
<p>Caelestia 這類「desktop shell 專案」做的就是把上述元件統一設計、統一配色、統一出貨，省去自己一個個挑的功夫。它用的是 Quickshell（QML 框架）把所有元件包成一套風格一致的桌面。本模組教的是自己組裝的方式——理解各元件的配置，之後要用 Caelestia 或自己拼都能做。</p>
<h2 id="waybar狀態列">Waybar：狀態列</h2>
<p>Waybar 是 Hyprland 桌面最常用的狀態列。配置在 <code>~/.config/waybar/</code>，分兩個檔案：<code>config.jsonc</code>（結構和模組）和 <code>style.css</code>（外觀）。</p>
<h3 id="結構配置">結構配置</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-jsonc" data-lang="jsonc"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// ~/.config/waybar/config.jsonc
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span><span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="nt">&#34;layer&#34;</span><span class="p">:</span> <span class="s2">&#34;top&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="nt">&#34;position&#34;</span><span class="p">:</span> <span class="s2">&#34;top&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="nt">&#34;height&#34;</span><span class="p">:</span> <span class="mi">36</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="nt">&#34;spacing&#34;</span><span class="p">:</span> <span class="mi">4</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="c1"></span>    <span class="nt">&#34;modules-left&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;hyprland/workspaces&#34;</span><span class="p">,</span> <span class="s2">&#34;hyprland/window&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="nt">&#34;modules-center&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;clock&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="nt">&#34;modules-right&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;pulseaudio&#34;</span><span class="p">,</span> <span class="s2">&#34;network&#34;</span><span class="p">,</span> <span class="s2">&#34;cpu&#34;</span><span class="p">,</span> <span class="s2">&#34;memory&#34;</span><span class="p">,</span> <span class="s2">&#34;battery&#34;</span><span class="p">,</span> <span class="s2">&#34;tray&#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">// 各模組設定
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1"></span>    <span class="nt">&#34;hyprland/workspaces&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="nt">&#34;format&#34;</span><span class="p">:</span> <span class="s2">&#34;{id}&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="nt">&#34;on-click&#34;</span><span class="p">:</span> <span class="s2">&#34;activate&#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="nt">&#34;clock&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="nt">&#34;format&#34;</span><span class="p">:</span> <span class="s2">&#34;{:%H:%M}&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="nt">&#34;format-alt&#34;</span><span class="p">:</span> <span class="s2">&#34;{:%Y-%m-%d %H:%M}&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="nt">&#34;tooltip-format&#34;</span><span class="p">:</span> <span class="s2">&#34;&lt;tt&gt;{calendar}&lt;/tt&gt;&#34;</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="nt">&#34;battery&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="nt">&#34;format&#34;</span><span class="p">:</span> <span class="s2">&#34;{capacity}% {icon}&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="nt">&#34;format-icons&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="nt">&#34;states&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">            <span class="nt">&#34;warning&#34;</span><span class="p">:</span> <span class="mi">30</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">            <span class="nt">&#34;critical&#34;</span><span class="p">:</span> <span class="mi">15</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <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="nt">&#34;network&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">        <span class="nt">&#34;format-wifi&#34;</span><span class="p">:</span> <span class="s2">&#34;{essid} ({signalStrength}%)&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">        <span class="nt">&#34;format-ethernet&#34;</span><span class="p">:</span> <span class="s2">&#34;{ifname}&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">        <span class="nt">&#34;format-disconnected&#34;</span><span class="p">:</span> <span class="s2">&#34;Disconnected&#34;</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">    <span class="nt">&#34;pulseaudio&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">        <span class="nt">&#34;format&#34;</span><span class="p">:</span> <span class="s2">&#34;{volume}%&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">        <span class="nt">&#34;on-click&#34;</span><span class="p">:</span> <span class="s2">&#34;pavucontrol&#34;</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p><code>format</code> 欄位裡的 icon 字元來自 Nerd Font——<a href="/blog/linux/dotfile/03-terminal-ecosystem/" data-link-title="模組三：終端機與編輯器" data-link-desc="終端機相關工具的配置檔散落在不同位置、不確定哪些該進 dotfile repo 時回來讀">終端機與編輯器</a>提到的字型安裝是這裡正常顯示的前提。</p>
<h3 id="外觀-css">外觀 CSS</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c">/* ~/.config/waybar/style.css */</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="o">*</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="k">font-family</span><span class="p">:</span> <span class="s2">&#34;MesloLGS Nerd Font&#34;</span><span class="p">,</span> <span class="kc">monospace</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">font-size</span><span class="p">:</span> <span class="mi">13</span><span class="kt">px</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></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="nt">window</span><span class="p">#</span><span class="nn">waybar</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="k">background-color</span><span class="p">:</span> <span class="nb">rgba</span><span class="p">(</span><span class="mi">30</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">46</span><span class="p">,</span> <span class="mf">0.85</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">color</span><span class="p">:</span> <span class="mh">#cdd6f4</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><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="p">#</span><span class="nn">workspaces</span> <span class="nt">button</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="k">padding</span><span class="p">:</span> <span class="mi">0</span> <span class="mi">8</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">color</span><span class="p">:</span> <span class="mh">#6c7086</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="k">border-radius</span><span class="p">:</span> <span class="mi">6</span><span class="kt">px</span><span class="p">;</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></span><span class="line"><span class="ln">19</span><span class="cl"><span class="p">#</span><span class="nn">workspaces</span> <span class="nt">button</span><span class="p">.</span><span class="nc">active</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="k">color</span><span class="p">:</span> <span class="mh">#cdd6f4</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="k">background</span><span class="p">:</span> <span class="nb">rgba</span><span class="p">(</span><span class="mi">137</span><span class="p">,</span> <span class="mi">180</span><span class="p">,</span> <span class="mi">250</span><span class="p">,</span> <span class="mf">0.2</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="p">#</span><span class="nn">clock</span><span class="o">,</span> <span class="p">#</span><span class="nn">battery</span><span class="o">,</span> <span class="p">#</span><span class="nn">network</span><span class="o">,</span> <span class="p">#</span><span class="nn">pulseaudio</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="k">padding</span><span class="p">:</span> <span class="mi">0</span> <span class="mi">10</span><span class="kt">px</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="p">#</span><span class="nn">battery</span><span class="p">.</span><span class="nc">warning</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="k">color</span><span class="p">:</span> <span class="mh">#f9e2af</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></span><span class="line"><span class="ln">32</span><span class="cl"><span class="p">#</span><span class="nn">battery</span><span class="p">.</span><span class="nc">critical</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="k">color</span><span class="p">:</span> <span class="mh">#f38ba8</span><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><p>CSS 裡的色碼（<code>#cdd6f4</code>、<code>#89b4fa</code>、<code>#f38ba8</code>）來自配色方案（這個範例用的是 Catppuccin Mocha）。統一使用同一套色碼是 rice 視覺協調的基礎。</p>
<p>Config 裡的字族名必須跟系統實際安裝的字族逐字相符。Nerd Font 的圖示落在專屬碼位範圍，只有對應的那支字帶這些 glyph——指定一個沒裝的字族名，文字排版引擎找不到 glyph 就會顯示豆腐方塊。確認實裝字族名的方式：</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">fc-list <span class="p">|</span> grep -i meslo
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># MesloLGSNerdFont-Regular.ttf: &#34;MesloLGS Nerd Font&#34;:style=Regular</span></span></span></code></pre></div><p>引號內的字串是 config 該填的字族名。</p>
<p>同一份 Waybar config 能同時服務筆電、桌機與 VM，靠的是模組對缺少硬體的自動退化：<code>battery</code> 在沒有電池的機器直接隱藏該模組、不報錯也不留空位；<code>pulseaudio</code> 在沒有音訊服務時顯示為空；<code>network</code> 顯示當下實際在用的介面。不必為不同機器維護多份 config——把可能用到的模組都列上，用不到的那台自己消失。</p>
<h2 id="wofi--rofi啟動器">Wofi / Rofi：啟動器</h2>
<p>啟動器是按快捷鍵彈出的搜尋框，用來啟動應用程式、執行指令、搜尋檔案。</p>
<p>Wofi（Wayland 原生）配置：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ini" data-lang="ini"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># ~/.config/wofi/config</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="na">show</span><span class="o">=</span><span class="s">drun</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="na">width</span><span class="o">=</span><span class="s">600</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="na">height</span><span class="o">=</span><span class="s">400</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="na">prompt</span><span class="o">=</span><span class="s">Search...</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="na">insensitive</span><span class="o">=</span><span class="s">true</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="na">allow_markup</span><span class="o">=</span><span class="s">true</span></span></span></code></pre></div>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c">/* ~/.config/wofi/style.css */</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="nt">window</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="k">background-color</span><span class="p">:</span> <span class="mh">#1e1e2e</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="k">border</span><span class="p">:</span> <span class="mi">2</span><span class="kt">px</span> <span class="kc">solid</span> <span class="mh">#89b4fa</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">border-radius</span><span class="p">:</span> <span class="mi">12</span><span class="kt">px</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></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="p">#</span><span class="nn">input</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="k">background-color</span><span class="p">:</span> <span class="mh">#313244</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">color</span><span class="p">:</span> <span class="mh">#cdd6f4</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">border-radius</span><span class="p">:</span> <span class="mi">8</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">margin</span><span class="p">:</span> <span class="mi">10</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="k">padding</span><span class="p">:</span> <span class="mi">8</span><span class="kt">px</span> <span class="mi">12</span><span class="kt">px</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></span><span class="line"><span class="ln">16</span><span class="cl"><span class="p">#</span><span class="nn">entry</span><span class="p">:</span><span class="nd">selected</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="k">background-color</span><span class="p">:</span> <span class="nb">rgba</span><span class="p">(</span><span class="mi">137</span><span class="p">,</span> <span class="mi">180</span><span class="p">,</span> <span class="mi">250</span><span class="p">,</span> <span class="mf">0.2</span><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>Rofi（需要 wayland fork rofi-lbonn-wayland）功能更豐富——支援多種 mode（drun、window、ssh、自定義 script）、主題系統更完整。如果需要進階功能（例如 emoji picker、密碼管理器整合），Rofi 是更好的選擇。</p>
<h2 id="mako--dunst通知">Mako / Dunst：通知</h2>
<p>Mako 是 Wayland 原生的通知 daemon，負責<strong>顯示</strong>通知——它監聽 D-Bus 的 <code>org.freedesktop.Notifications</code> 介面、把收到的通知畫出來。產生通知的是應用程式，透過 <code>libnotify</code> 送上 D-Bus。所以一套能用的通知鏈需要兩半：daemon（顯示）和 <code>libnotify</code>（產生與遞送）。缺了 <code>libnotify</code>，連命令列自測用的 <code>notify-send</code> 都沒有。套件清單要同時列 <code>mako</code> 和 <code>libnotify</code>。</p>
<p>配置簡潔：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ini" data-lang="ini"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># ~/.config/mako/config</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="na">font</span><span class="o">=</span><span class="s">MesloLGS Nerd Font 11</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="na">background-color</span><span class="o">=</span><span class="s">#1e1e2e</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="na">text-color</span><span class="o">=</span><span class="s">#cdd6f4</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="na">border-color</span><span class="o">=</span><span class="s">#89b4fa</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="na">border-radius</span><span class="o">=</span><span class="s">8</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="na">border-size</span><span class="o">=</span><span class="s">2</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="na">padding</span><span class="o">=</span><span class="s">12</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="na">default-timeout</span><span class="o">=</span><span class="s">5000</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="na">max-visible</span><span class="o">=</span><span class="s">3</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="k">[urgency=critical]</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="na">border-color</span><span class="o">=</span><span class="s">#f38ba8</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="na">default-timeout</span><span class="o">=</span><span class="s">0</span></span></span></code></pre></div><p>通知的視覺風格（圓角、配色、字型）要跟 waybar 和啟動器一致，這是整體 rice 不散的關鍵。</p>
<p>Nerd Font 的字符集只含 Latin、圖示與 Powerline 符號，不含中日韓。任何 CJK 文字（通知內文、視窗標題）若系統沒有 CJK 字型可 fallback 會變豆腐方塊。修法是安裝 CJK fallback（如 <code>noto-fonts-cjk</code>），fontconfig 會自動補字、不需改各工具的 config。另外，中途補裝字型後已在跑的 daemon 需重啟才看得到——<code>reload</code> 類指令只重讀設定檔、不重建記憶體中的字型快照（原理見 <a href="/blog/linux/dotfile/knowledge-cards/font-availability-at-startup/" data-link-title="字型的可用集合在 process 啟動時決定" data-link-desc="裝了字型但應用程式 / 狀態列 / 通知還是看不到、還是豆腐時回來讀">字型的可用集合在 process 啟動時決定</a>）。</p>
<h2 id="grim--slurp截圖">Grim + Slurp：截圖</h2>
<p>Grim 負責截圖、Slurp 負責框選區域，兩者搭配使用。截圖結果透過 <code>wl-copy</code> 送進剪貼簿時，需要明確指定 MIME 型別：</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="c1"># 全螢幕截圖到剪貼簿</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">grim - <span class="p">|</span> wl-copy --type image/png
</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"># 框選區域截圖到剪貼簿</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">grim -g <span class="s2">&#34;</span><span class="k">$(</span>slurp<span class="k">)</span><span class="s2">&#34;</span> - <span class="p">|</span> wl-copy --type image/png
</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">grim ~/screenshot.png</span></span></code></pre></div><p><code>wl-copy</code> 不帶 <code>--type</code> 時會嘗試透過 <code>xdg-utils</code>（<code>xdg-mime</code>）推斷 stdin 的型別。最小安裝環境沒有 <code>xdg-utils</code> 的情況下，PNG bytes 會被誤標成 <code>text/plain</code>，貼進影像應用程式就拿不到圖。明確帶 <code>--type image/png</code> 讓行為不依賴環境是否安裝了 <code>xdg-utils</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">wl-paste --list-types
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 應顯示 image/png</span></span></span></code></pre></div><p>Hyprland keybind 範例：</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="nb">bind</span> <span class="o">=</span> , Print, exec, grim - <span class="p">|</span> wl-copy --type image/png
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nb">bind</span> <span class="o">=</span> SHIFT, Print, exec, grim -g <span class="s2">&#34;</span><span class="k">$(</span>slurp<span class="k">)</span><span class="s2">&#34;</span> - <span class="p">|</span> wl-copy --type image/png</span></span></code></pre></div>]]></content:encoded></item><item><title>整合式 Shell vs 手動拼裝：實測足跡、失敗半徑與選型判準</title><link>https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/integrated-shell-vs-manual-assembly/</link><pubDate>Wed, 01 Jul 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/integrated-shell-vs-manual-assembly/</guid><description>&lt;p>整合式桌面 shell 與手動拼裝，是「一個大程式包辦整個桌面」與「多個小程式各司其職、由 compositor 黏起來」兩種架構。&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/caelestia-overview/" data-link-title="Caelestia 總覽：預組裝的 Hyprland 桌面 Shell" data-link-desc="考慮用 Caelestia 取代手動拼裝 waybar&amp;#43;wofi&amp;#43;mako、或評估預組裝桌面 shell 的 trade-off 時回來讀">Caelestia 總覽&lt;/a> 從概念層談過它的取捨（設計鎖定、穩定性風險）；這篇補上在同一台機器上實際跑過兩種之後量到的數據——資源足跡、失敗半徑、配色一致性——把「感覺整合比較方便」變成可以拿數字判斷的選型。&lt;/p>
&lt;p>這裡的數據來自一次 VM 實測：先手動拼裝一套 waybar + wofi + mako + hyprlock，再換成 Caelestia，量兩者的安裝大小、記憶體、config 結構與失敗行為。&lt;/p>
&lt;h2 id="資源足跡差約一個數量級">資源足跡：差約一個數量級&lt;/h2>
&lt;p>整合式 shell 把整個桌面畫在一個程式裡，這個程式通常是重量級的 UI runtime。Caelestia 建在 Quickshell（Qt6/QML）上，實測安裝足跡如下：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>項目&lt;/th>
 &lt;th>整合式（Caelestia）&lt;/th>
 &lt;th>手動拼裝（waybar+wofi+mako+hyprlock）&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>安裝大小&lt;/td>
 &lt;td>約 230 MB（Quickshell 佔 213 MB）&lt;/td>
 &lt;td>約 4.5 MB（waybar 3 MB，其餘 KB 級）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>執行記憶體 RSS&lt;/td>
 &lt;td>單一 &lt;code>qs&lt;/code> 程式約 400 MB&lt;/td>
 &lt;td>waybar 約 53 MB + 通知/啟動器（小）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>差距的來源是 Quickshell 這個 UI 框架——那 213 MB 是 &lt;code>quickshell&lt;/code> 套件本身的安裝大小（一個建在 Qt6 上的 QML shell runtime），不是 Caelestia 的功能程式碼；而且 Qt6 的函式庫（&lt;code>qt6-declarative&lt;/code>、&lt;code>qt6-base&lt;/code> 等）還是它之上的額外相依，沒算進這 213 MB。手動拼裝的 waybar、wofi、mako 都是輕量的 wlroots/GTK 程式，加起來還不到 5 MB。&lt;/p>
&lt;p>這一軸在資源受限的機器上才會咬人：舊筆電、記憶體小的 VPS、或你本來就想把桌面壓到最輕。在一台記憶體充裕的桌機上，400 MB 對 60 MB 的差別多半感覺不到；在一台 2 GB RAM 的機器上，這就是「桌面吃掉五分之一記憶體」跟「幾乎不佔」的差別。&lt;/p>
&lt;h2 id="失敗半徑單點-vs-各自獨立">失敗半徑：單點 vs 各自獨立&lt;/h2>
&lt;p>整合式 shell 把狀態列、通知、鎖屏、啟動器畫在&lt;strong>同一個程式&lt;/strong>裡，所以這個程式崩潰時，這些東西會&lt;strong>一起消失&lt;/strong>。手動拼裝的每個元件是獨立行程，一個崩掉不影響其他——mako（通知）崩了，waybar（狀態列）還在。&lt;/p>
&lt;p>這不只是理論。這次 VM 實測就撞到一個具體案例：Caelestia 的鎖屏是由 Quickshell 主程式畫的，當這個持鎖的程式被中止時，Hyprland 依 &lt;code>ext-session-lock&lt;/code> 協議保持鎖定並顯示「lockscreen app died」的死局——狀態列、通知、鎖屏因為同源，一個環節出事就連帶整個桌面 UI。手動拼裝的 hyprlock 是獨立的鎖屏程式，它崩潰同樣會觸發那個死局，但你的狀態列與通知不會跟著沒。&lt;/p>
&lt;p>這一軸在穩定性敏感或無人值守的場景最關鍵。跑長時間無人盯著的任務時，「一個元件崩掉只損失那個元件」的隔離性，比「全部整合在一起」的一致性更值錢——因為沒人在旁邊立刻重啟。&lt;/p>
&lt;h2 id="配色一致性最容易被低估的一軸">配色一致性：最容易被低估的一軸&lt;/h2>
&lt;p>讓整個桌面配色一致，是整合式與手動拼裝差別最大、卻最常被忽略的地方。整合式 shell 因為所有元件在同一個程式裡，天生共用一套配色——Caelestia 的 dynamic scheme 從桌布抽一組 Material-3 palette，狀態列、通知、鎖屏、dashboard 全部同時套用，換張桌布整套 UI 跟著變。&lt;/p>
&lt;p>手動拼裝要達到同樣的一致，得自己解決一個跨程式的問題：每個元件用不同的設定格式與主題引擎，它們之間不會自動共享顏色。這次手動拼裝那套時就撞到這點——waybar 的 GTK CSS 引擎讀不到 Hyprland 的 &lt;code>$&lt;/code> 顏色變數，結果 waybar 的 &lt;code>style.css&lt;/code> 裡得&lt;strong>手抄一份跟 Hyprland &lt;code>colors.conf&lt;/code> 相同的 hex 色碼&lt;/strong>。換一次配色，就要在 waybar CSS、wofi CSS、mako config、hyprland colors 好幾個地方各改一遍。&lt;/p>
&lt;p>解這個手工問題的標準做法，是加一層&lt;strong>模板工具&lt;/strong>（matugen、pywal、wallust 之類）：從一張桌布或一套色票，自動生成每個元件的設定檔（例如 &lt;code>matugen/templates/rofi-colors.rasi&lt;/code> 就是給 rofi 用的顏色模板）。這等於是手動重建 Caelestia 內建的那套 dynamic theming pipeline。所以配色一致這件事的真正取捨是：Caelestia 開箱就有「換桌布全套跟著變」，手動拼裝要嘛手抄 hex、要嘛自己搭一條 templating pipeline。&lt;/p>
&lt;h2 id="config-結構">config 結構&lt;/h2>
&lt;p>配色一致的差別，也反映在 config 的形狀上。Caelestia 的使用者設定集中在一個 &lt;code>shell.json&lt;/code>（實測約 24 行就涵蓋狀態列、通知、idle 行為）。手動拼裝的設定散在各元件目錄、各用各的格式：waybar 的 &lt;code>config.jsonc&lt;/code> + &lt;code>style.css&lt;/code>、wofi 的 &lt;code>config&lt;/code> + &lt;code>style.css&lt;/code>、mako 的 &lt;code>config&lt;/code>、hypr 的數個 &lt;code>.conf&lt;/code>。集中的好處是好懂好改；散開的好處是每個元件可以獨立替換（把 waybar 換成 ironbar 不影響其他），代價是你要管更多檔案、更多格式。&lt;/p></description><content:encoded><![CDATA[<p>整合式桌面 shell 與手動拼裝，是「一個大程式包辦整個桌面」與「多個小程式各司其職、由 compositor 黏起來」兩種架構。<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> 從概念層談過它的取捨（設計鎖定、穩定性風險）；這篇補上在同一台機器上實際跑過兩種之後量到的數據——資源足跡、失敗半徑、配色一致性——把「感覺整合比較方便」變成可以拿數字判斷的選型。</p>
<p>這裡的數據來自一次 VM 實測：先手動拼裝一套 waybar + wofi + mako + hyprlock，再換成 Caelestia，量兩者的安裝大小、記憶體、config 結構與失敗行為。</p>
<h2 id="資源足跡差約一個數量級">資源足跡：差約一個數量級</h2>
<p>整合式 shell 把整個桌面畫在一個程式裡，這個程式通常是重量級的 UI runtime。Caelestia 建在 Quickshell（Qt6/QML）上，實測安裝足跡如下：</p>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>整合式（Caelestia）</th>
          <th>手動拼裝（waybar+wofi+mako+hyprlock）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>安裝大小</td>
          <td>約 230 MB（Quickshell 佔 213 MB）</td>
          <td>約 4.5 MB（waybar 3 MB，其餘 KB 級）</td>
      </tr>
      <tr>
          <td>執行記憶體 RSS</td>
          <td>單一 <code>qs</code> 程式約 400 MB</td>
          <td>waybar 約 53 MB + 通知/啟動器（小）</td>
      </tr>
  </tbody>
</table>
<p>差距的來源是 Quickshell 這個 UI 框架——那 213 MB 是 <code>quickshell</code> 套件本身的安裝大小（一個建在 Qt6 上的 QML shell runtime），不是 Caelestia 的功能程式碼；而且 Qt6 的函式庫（<code>qt6-declarative</code>、<code>qt6-base</code> 等）還是它之上的額外相依，沒算進這 213 MB。手動拼裝的 waybar、wofi、mako 都是輕量的 wlroots/GTK 程式，加起來還不到 5 MB。</p>
<p>這一軸在資源受限的機器上才會咬人：舊筆電、記憶體小的 VPS、或你本來就想把桌面壓到最輕。在一台記憶體充裕的桌機上，400 MB 對 60 MB 的差別多半感覺不到；在一台 2 GB RAM 的機器上，這就是「桌面吃掉五分之一記憶體」跟「幾乎不佔」的差別。</p>
<h2 id="失敗半徑單點-vs-各自獨立">失敗半徑：單點 vs 各自獨立</h2>
<p>整合式 shell 把狀態列、通知、鎖屏、啟動器畫在<strong>同一個程式</strong>裡，所以這個程式崩潰時，這些東西會<strong>一起消失</strong>。手動拼裝的每個元件是獨立行程，一個崩掉不影響其他——mako（通知）崩了，waybar（狀態列）還在。</p>
<p>這不只是理論。這次 VM 實測就撞到一個具體案例：Caelestia 的鎖屏是由 Quickshell 主程式畫的，當這個持鎖的程式被中止時，Hyprland 依 <code>ext-session-lock</code> 協議保持鎖定並顯示「lockscreen app died」的死局——狀態列、通知、鎖屏因為同源，一個環節出事就連帶整個桌面 UI。手動拼裝的 hyprlock 是獨立的鎖屏程式，它崩潰同樣會觸發那個死局，但你的狀態列與通知不會跟著沒。</p>
<p>這一軸在穩定性敏感或無人值守的場景最關鍵。跑長時間無人盯著的任務時，「一個元件崩掉只損失那個元件」的隔離性，比「全部整合在一起」的一致性更值錢——因為沒人在旁邊立刻重啟。</p>
<h2 id="配色一致性最容易被低估的一軸">配色一致性：最容易被低估的一軸</h2>
<p>讓整個桌面配色一致，是整合式與手動拼裝差別最大、卻最常被忽略的地方。整合式 shell 因為所有元件在同一個程式裡，天生共用一套配色——Caelestia 的 dynamic scheme 從桌布抽一組 Material-3 palette，狀態列、通知、鎖屏、dashboard 全部同時套用，換張桌布整套 UI 跟著變。</p>
<p>手動拼裝要達到同樣的一致，得自己解決一個跨程式的問題：每個元件用不同的設定格式與主題引擎，它們之間不會自動共享顏色。這次手動拼裝那套時就撞到這點——waybar 的 GTK CSS 引擎讀不到 Hyprland 的 <code>$</code> 顏色變數，結果 waybar 的 <code>style.css</code> 裡得<strong>手抄一份跟 Hyprland <code>colors.conf</code> 相同的 hex 色碼</strong>。換一次配色，就要在 waybar CSS、wofi CSS、mako config、hyprland colors 好幾個地方各改一遍。</p>
<p>解這個手工問題的標準做法，是加一層<strong>模板工具</strong>（matugen、pywal、wallust 之類）：從一張桌布或一套色票，自動生成每個元件的設定檔（例如 <code>matugen/templates/rofi-colors.rasi</code> 就是給 rofi 用的顏色模板）。這等於是手動重建 Caelestia 內建的那套 dynamic theming pipeline。所以配色一致這件事的真正取捨是：Caelestia 開箱就有「換桌布全套跟著變」，手動拼裝要嘛手抄 hex、要嘛自己搭一條 templating pipeline。</p>
<h2 id="config-結構">config 結構</h2>
<p>配色一致的差別，也反映在 config 的形狀上。Caelestia 的使用者設定集中在一個 <code>shell.json</code>（實測約 24 行就涵蓋狀態列、通知、idle 行為）。手動拼裝的設定散在各元件目錄、各用各的格式：waybar 的 <code>config.jsonc</code> + <code>style.css</code>、wofi 的 <code>config</code> + <code>style.css</code>、mako 的 <code>config</code>、hypr 的數個 <code>.conf</code>。集中的好處是好懂好改；散開的好處是每個元件可以獨立替換（把 waybar 換成 ironbar 不影響其他），代價是你要管更多檔案、更多格式。</p>
<h2 id="選型判準">選型判準</h2>
<p>沒有一種在所有軸上都贏。依你的情境對照：</p>
<table>
  <thead>
      <tr>
          <th>你的情境</th>
          <th>偏向</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>資源受限（舊機、小 RAM VPS）</td>
          <td>手動拼裝（省下那 ~340 MB 記憶體）</td>
      </tr>
      <tr>
          <td>想要開箱即用、換桌布全套變色</td>
          <td>整合式（Caelestia 的 dynamic 原生就有）</td>
      </tr>
      <tr>
          <td>穩定性敏感、無人值守</td>
          <td>手動拼裝（元件獨立、失敗半徑小）</td>
      </tr>
      <tr>
          <td>想要結構性客製（狀態列位置、換 launcher）</td>
          <td>手動拼裝（整合式的結構是 shell 決定的）</td>
      </tr>
      <tr>
          <td>想少管檔案、快速有一套設計一致的成品</td>
          <td>整合式（一個 config、一套配色）</td>
      </tr>
      <tr>
          <td>已經在跑 templating 工具（matugen/pywal）</td>
          <td>手動拼裝（你已經有一致配色的機制、少了整合式的理由）</td>
      </tr>
  </tbody>
</table>
<h3 id="重新評估的訊號tripwire">重新評估的訊號（tripwire）</h3>
<p>選了之後，出現這些訊號時值得回頭重新評估：</p>
<ul>
<li>選了整合式，卻發現一直在跟它的設計決策對抗（想改的結構它不讓你改）——你要的其實是手動拼裝的自由度。</li>
<li>選了手動拼裝，卻發現配色維護（每次改色手抄多個檔案）吃掉大量時間——該加 templating 工具，或重新考慮整合式。</li>
<li>記憶體壓力浮現（整合式的 Qt runtime 在小機器上排擠其他程式）——往手動拼裝退。</li>
<li>整合式的一次更新靜默破壞了你的自訂設定（<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 README 明言 config 可能無預警變動</a>）——評估這層快速移動的依賴值不值得。</li>
</ul>
<h2 id="下一步">下一步</h2>
<ul>
<li>整合式 shell 的概念定位、跟 AGS/Eww 的比較、三個 repo 的分工，見 <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>。</li>
<li>手動拼裝那幾個元件（狀態列、啟動器、通知）各自怎麼配置，見 <a href="/blog/linux/dotfile/06-rice-design/desktop-shell-components/" data-link-title="桌面 Shell 元件：狀態列、啟動器與通知" data-link-desc="Hyprland 桌面要拼哪些元件、各元件的配置檔怎麼寫時回來讀">桌面 Shell 元件</a>。</li>
<li>配色系統本身（不管哪條路線）怎麼設計，見 <a href="/blog/linux/dotfile/06-rice-design/color-system-theming/" data-link-title="配色系統、鎖屏與 GTK 主題" data-link-desc="桌面配色散亂看起來雜、或要換主題不知道該改哪些檔案時回來讀">配色系統、鎖屏與 GTK 主題</a>。</li>
</ul>
<p>這篇的足跡數字（安裝 230 MB vs 4.5 MB、RSS ~400 MB vs ~60 MB）與 lock-died 失敗案例，來自一次在 Apple Silicon UTM VM 上實際跑過兩種桌面棧的量測。</p>
]]></content:encoded></item><item><title>模組六：桌面 Rice 設計</title><link>https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/</link><pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/</guid><description>&lt;p>Rice 在 Linux 桌面社群指的是桌面視覺客製化——把系統外觀調教成個人化的美學呈現。這個詞源自汽車改裝文化（Race Inspired Cosmetic Enhancements 的逆向縮寫），在 Linux 圈已轉為中性的圈內用語，r/unixporn 社群就是圍繞這件事運轉的。&lt;/p>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/05-hyprland-config/" data-link-title="模組五：Hyprland 配置" data-link-desc="要在 Linux 上設定 Hyprland 平鋪式桌面時回來讀">Hyprland 配置&lt;/a>教了 compositor（Wayland 下負責視窗排列和畫面合成的程式）本身的設定。這個模組處理的是 compositor 之上的「桌面 shell」層——狀態列、啟動器、通知、鎖屏、桌布、配色系統。做法有兩條路：自己從 Waybar + Wofi + Mako 等獨立工具一個個拼裝，或用 Caelestia 這類預組裝的桌面 shell 一次部署。&lt;/p>
&lt;h2 id="章節文章">章節文章&lt;/h2>
&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;a href="https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/desktop-shell-components/" data-link-title="桌面 Shell 元件：狀態列、啟動器與通知" data-link-desc="Hyprland 桌面要拼哪些元件、各元件的配置檔怎麼寫時回來讀">桌面 Shell 元件：狀態列、啟動器與通知&lt;/a>&lt;/td>
 &lt;td>拼裝式桌面的元件組成、Waybar 狀態列配置、Wofi/Rofi 啟動器、Mako 通知&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/color-system-theming/" data-link-title="配色系統、鎖屏與 GTK 主題" data-link-desc="桌面配色散亂看起來雜、或要換主題不知道該改哪些檔案時回來讀">配色系統、鎖屏與 GTK 主題&lt;/a>&lt;/td>
 &lt;td>Hyprlock 鎖屏配置、配色變數集中管理、GTK/Qt 主題統一、投資報酬判讀&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/caelestia-overview/" data-link-title="Caelestia 總覽：預組裝的 Hyprland 桌面 Shell" data-link-desc="考慮用 Caelestia 取代手動拼裝 waybar&amp;#43;wofi&amp;#43;mako、或評估預組裝桌面 shell 的 trade-off 時回來讀">Caelestia 總覽&lt;/a>&lt;/td>
 &lt;td>Quickshell 框架、提供的元件、跟手動拼裝和 AGS/Eww 的 trade-off、定位認知&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/caelestia-installation/" data-link-title="Caelestia 安裝" data-link-desc="要在 Arch Linux 上安裝 Caelestia 桌面 shell 時回來讀">Caelestia 安裝&lt;/a>&lt;/td>
 &lt;td>AUR 套件、CLI 安裝流程、依賴清單、登入管理器、CLI 指令、VM 測試範圍&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/caelestia-configuration/" data-link-title="Caelestia 配置" data-link-desc="安裝完 Caelestia 後要客製化設定時回來讀">Caelestia 配置&lt;/a>&lt;/td>
 &lt;td>shell.json 結構、token 系統、hypr-user.lua、動態取色、已知問題、dotfile 結構&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/06-rice-design/integrated-shell-vs-manual-assembly/" data-link-title="整合式 Shell vs 手動拼裝：實測足跡、失敗半徑與選型判準" data-link-desc="在整合式桌面 shell（如 Caelestia）與手動拼裝 waybar&amp;#43;wofi&amp;#43;mako 之間選型、需要實測的資源足跡、失敗半徑與配色一致性數據來判斷時回來讀">整合式 Shell vs 手動拼裝：實測取捨&lt;/a>&lt;/td>
 &lt;td>兩種桌面棧的實測足跡（安裝/記憶體）、失敗半徑、配色一致性機制與選型判準&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="跨分類引用">跨分類引用&lt;/h2>
&lt;ul>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/03-terminal-ecosystem/" data-link-title="模組三：終端機與編輯器" data-link-desc="終端機相關工具的配置檔散落在不同位置、不確定哪些該進 dotfile repo 時回來讀">模組三：終端機與編輯器&lt;/a>：Nerd Font 安裝是 Waybar icon 正常顯示的前提&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/05-hyprland-config/" data-link-title="模組五：Hyprland 配置" data-link-desc="要在 Linux 上設定 Hyprland 平鋪式桌面時回來讀">模組五：Hyprland 配置&lt;/a>：compositor 的 appearance 設定（圓角、動畫）跟 rice 的視覺層互補&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/01-dotfile-management/" data-link-title="模組一：管理工具與目錄結構" data-link-desc="要把散落在家目錄的配置檔集中版控時，選 bare repo、stow 還是 chezmoi、目錄該怎麼組織">模組一：管理工具與目錄結構&lt;/a>：各 rice 元件的配置檔怎麼放進 stow 結構&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/session-lock/" data-link-title="Wayland Session Lock（鎖屏安全狀態）" data-link-desc="hyprlock / swaylock 畫面卡住、pkill 後進不了桌面、或要在 VM / 自動化環境測試鎖屏時回來讀">Session Lock&lt;/a>：鎖屏的安全模型——殺 process 不等於解鎖&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/font-availability-at-startup/" data-link-title="字型的可用集合在 process 啟動時決定" data-link-desc="裝了字型但應用程式 / 狀態列 / 通知還是看不到、還是豆腐時回來讀">字型的可用集合在 process 啟動時決定&lt;/a>：裝了字型但狀態列 / 通知還是豆腐時的判讀&lt;/li>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/fontconfig/" data-link-title="fontconfig — 字型搜尋、匹配與 fallback 服務" data-link-desc="不確定 fc-list / fc-match / fc-cache 各做什麼、或 fontconfig fallback 機制怎麼運作時回來讀">fontconfig&lt;/a>：字型搜尋、匹配與 fallback 機制&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Rice 在 Linux 桌面社群指的是桌面視覺客製化——把系統外觀調教成個人化的美學呈現。這個詞源自汽車改裝文化（Race Inspired Cosmetic Enhancements 的逆向縮寫），在 Linux 圈已轉為中性的圈內用語，r/unixporn 社群就是圍繞這件事運轉的。</p>
<p><a href="/blog/linux/dotfile/05-hyprland-config/" data-link-title="模組五：Hyprland 配置" data-link-desc="要在 Linux 上設定 Hyprland 平鋪式桌面時回來讀">Hyprland 配置</a>教了 compositor（Wayland 下負責視窗排列和畫面合成的程式）本身的設定。這個模組處理的是 compositor 之上的「桌面 shell」層——狀態列、啟動器、通知、鎖屏、桌布、配色系統。做法有兩條路：自己從 Waybar + Wofi + Mako 等獨立工具一個個拼裝，或用 Caelestia 這類預組裝的桌面 shell 一次部署。</p>
<h2 id="章節文章">章節文章</h2>
<table>
  <thead>
      <tr>
          <th>文章</th>
          <th>主題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/linux/dotfile/06-rice-design/desktop-shell-components/" data-link-title="桌面 Shell 元件：狀態列、啟動器與通知" data-link-desc="Hyprland 桌面要拼哪些元件、各元件的配置檔怎麼寫時回來讀">桌面 Shell 元件：狀態列、啟動器與通知</a></td>
          <td>拼裝式桌面的元件組成、Waybar 狀態列配置、Wofi/Rofi 啟動器、Mako 通知</td>
      </tr>
      <tr>
          <td><a href="/blog/linux/dotfile/06-rice-design/color-system-theming/" data-link-title="配色系統、鎖屏與 GTK 主題" data-link-desc="桌面配色散亂看起來雜、或要換主題不知道該改哪些檔案時回來讀">配色系統、鎖屏與 GTK 主題</a></td>
          <td>Hyprlock 鎖屏配置、配色變數集中管理、GTK/Qt 主題統一、投資報酬判讀</td>
      </tr>
      <tr>
          <td><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></td>
          <td>Quickshell 框架、提供的元件、跟手動拼裝和 AGS/Eww 的 trade-off、定位認知</td>
      </tr>
      <tr>
          <td><a href="/blog/linux/dotfile/06-rice-design/caelestia-installation/" data-link-title="Caelestia 安裝" data-link-desc="要在 Arch Linux 上安裝 Caelestia 桌面 shell 時回來讀">Caelestia 安裝</a></td>
          <td>AUR 套件、CLI 安裝流程、依賴清單、登入管理器、CLI 指令、VM 測試範圍</td>
      </tr>
      <tr>
          <td><a href="/blog/linux/dotfile/06-rice-design/caelestia-configuration/" data-link-title="Caelestia 配置" data-link-desc="安裝完 Caelestia 後要客製化設定時回來讀">Caelestia 配置</a></td>
          <td>shell.json 結構、token 系統、hypr-user.lua、動態取色、已知問題、dotfile 結構</td>
      </tr>
      <tr>
          <td><a href="/blog/linux/dotfile/06-rice-design/integrated-shell-vs-manual-assembly/" data-link-title="整合式 Shell vs 手動拼裝：實測足跡、失敗半徑與選型判準" data-link-desc="在整合式桌面 shell（如 Caelestia）與手動拼裝 waybar&#43;wofi&#43;mako 之間選型、需要實測的資源足跡、失敗半徑與配色一致性數據來判斷時回來讀">整合式 Shell vs 手動拼裝：實測取捨</a></td>
          <td>兩種桌面棧的實測足跡（安裝/記憶體）、失敗半徑、配色一致性機制與選型判準</td>
      </tr>
  </tbody>
</table>
<h2 id="跨分類引用">跨分類引用</h2>
<ul>
<li>→ <a href="/blog/linux/dotfile/03-terminal-ecosystem/" data-link-title="模組三：終端機與編輯器" data-link-desc="終端機相關工具的配置檔散落在不同位置、不確定哪些該進 dotfile repo 時回來讀">模組三：終端機與編輯器</a>：Nerd Font 安裝是 Waybar icon 正常顯示的前提</li>
<li>→ <a href="/blog/linux/dotfile/05-hyprland-config/" data-link-title="模組五：Hyprland 配置" data-link-desc="要在 Linux 上設定 Hyprland 平鋪式桌面時回來讀">模組五：Hyprland 配置</a>：compositor 的 appearance 設定（圓角、動畫）跟 rice 的視覺層互補</li>
<li>→ <a href="/blog/linux/dotfile/01-dotfile-management/" data-link-title="模組一：管理工具與目錄結構" data-link-desc="要把散落在家目錄的配置檔集中版控時，選 bare repo、stow 還是 chezmoi、目錄該怎麼組織">模組一：管理工具與目錄結構</a>：各 rice 元件的配置檔怎麼放進 stow 結構</li>
<li>→ <a href="/blog/linux/dotfile/knowledge-cards/session-lock/" data-link-title="Wayland Session Lock（鎖屏安全狀態）" data-link-desc="hyprlock / swaylock 畫面卡住、pkill 後進不了桌面、或要在 VM / 自動化環境測試鎖屏時回來讀">Session Lock</a>：鎖屏的安全模型——殺 process 不等於解鎖</li>
<li>→ <a href="/blog/linux/dotfile/knowledge-cards/font-availability-at-startup/" data-link-title="字型的可用集合在 process 啟動時決定" data-link-desc="裝了字型但應用程式 / 狀態列 / 通知還是看不到、還是豆腐時回來讀">字型的可用集合在 process 啟動時決定</a>：裝了字型但狀態列 / 通知還是豆腐時的判讀</li>
<li>→ <a href="/blog/linux/dotfile/knowledge-cards/fontconfig/" data-link-title="fontconfig — 字型搜尋、匹配與 fallback 服務" data-link-desc="不確定 fc-list / fc-match / fc-cache 各做什麼、或 fontconfig fallback 機制怎麼運作時回來讀">fontconfig</a>：字型搜尋、匹配與 fallback 機制</li>
</ul>
]]></content:encoded></item></channel></rss>