<?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>Linux Experience on Code is cheap, let&#39;s talk</title>
    <link>https://blog.ferstar.org/series/linux-experience/</link>
    <description>Code is cheap, let&#39;s talk</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh-cn</language>
    <copyright>Copyright 2026 ferstar</copyright>
    <lastBuildDate>Tue, 25 Apr 2023 02:40:04 +0800</lastBuildDate>
    <ttl>60</ttl><atom:link href="https://blog.ferstar.org/series/linux-experience/index.xml" rel="self" type="application/rss+xml" /><image>
      <url>https://blog.ferstar.org/site-logo.png</url>
      <title>Code is cheap, let&#39;s talk</title>
      <link>https://blog.ferstar.org/</link>
    </image>
    
    <item>
      <title>如何在Linux X11开启R9000P2021款笔记本165Hz刷新率</title>
      <link>https://blog.ferstar.org/posts/r9000p-165hz-linux-x11/</link>
      <pubDate>Tue, 25 Apr 2023 02:40:04 +0800</pubDate>
      
      <guid isPermaLink="true">https://blog.ferstar.org/posts/r9000p-165hz-linux-x11/</guid>
      <description>解决联想拯救者 R9000P 在 Linux X11 环境下刷新率锁定或无法开启 165Hz 的问题，优化高刷显示效果，提升系统交互流畅度。</description><content:encoded><![CDATA[<p>我这款本子是 3050Ti 的显卡，Linux 下偶尔炼个超迷你小丹凑合用一下，平常大部分时候都是闲置状态，所以多数情况用的是<strong>混合模式</strong>而非<strong>独显直通</strong>。</p>
<p>这样有个问题，不管是 Archlinux 还是 Ubuntu，进桌面显示器配置就只有 60Hz 的选项，但切到<strong>独显直通</strong>，165Hz 的高刷就又有了，一通搜索以后，得出结论：在混合模式下系统无法准确获取EDID文件。另外即使是<strong>独显直通</strong>状态，屏幕回报的刷新率是 165.02Hz，说明这块屏幕不是标准的 165Hz 行刷新率，操作系统并没有正确的屏幕分辨率信息。</p>
<p>我在这里 <a href="https://wiki.archlinux.org/title/xrandr#Troubleshooting"  target="_blank" rel="noreferrer">https://wiki.archlinux.org/title/xrandr#Troubleshooting</a> 找到了这个问题的解决办法：</p>
<p>先在<strong>独显直通</strong>状态，通过<code>xrandr --verbose</code>记下 60、165Hz 的 Modeline，我的机器是这样的：</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># 60Hz</span>
</span></span><span class="line"><span class="cl">282.7 <span class="m">2560</span> <span class="m">2608</span> <span class="m">2640</span> <span class="m">2720</span> <span class="m">1600</span> <span class="m">1603</span> <span class="m">1609</span> <span class="m">1732</span> -HSync -VSync
</span></span><span class="line"><span class="cl"><span class="c1"># 165Hz</span>
</span></span><span class="line"><span class="cl">777.410 <span class="m">2560</span> <span class="m">2608</span> <span class="m">2640</span> <span class="m">2720</span> <span class="m">1600</span> <span class="m">1603</span> <span class="m">1609</span> <span class="m">1732</span> -HSync -VSync</span></span></code></pre></div></div>
<p>接下来就是把这两种配置用<code>xrandr</code>添加到内屏配置上，由于<strong>混合模式</strong>和<strong>独显直通</strong>两种模式下，内屏设备名并不固定，可以通过如下命令找到：</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">xrandr <span class="p">|</span> grep -i <span class="s1">' connected'</span> <span class="p">|</span> cut -d <span class="s1">' '</span> -f <span class="m">1</span></span></span></code></pre></div></div>
<p>我的机器输出如下：</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">eDP-1
</span></span><span class="line"><span class="cl">DP-1-0  <span class="c1"># 这个其实是我的外接屏幕</span></span></span></code></pre></div></div>
<p>确定好内屏设备名（eDP-1）以后，就可以来指定我们上面探测到的分辨率配置了：</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># 65Hz</span>
</span></span><span class="line"><span class="cl">xrandr --newmode <span class="s2">"2560x1600_60.00"</span> 282.7 <span class="m">2560</span> <span class="m">2608</span> <span class="m">2640</span> <span class="m">2720</span> <span class="m">1600</span> <span class="m">1603</span> <span class="m">1609</span> <span class="m">1732</span> -HSync -VSync
</span></span><span class="line"><span class="cl">xrandr --addmode eDP-1 2560x1600_60.00
</span></span><span class="line"><span class="cl"><span class="c1"># 165Hz</span>
</span></span><span class="line"><span class="cl">xrandr --newmode <span class="s2">"2560x1600_165.00"</span> 777.410 <span class="m">2560</span> <span class="m">2608</span> <span class="m">2640</span> <span class="m">2720</span> <span class="m">1600</span> <span class="m">1603</span> <span class="m">1609</span> <span class="m">1732</span> -HSync -VSync
</span></span><span class="line"><span class="cl">xrandr --addmode eDP-1 2560x1600_165.00</span></span></code></pre></div></div>
<p>此时打开显示器配置，熟悉的高刷分辨率就回来了，且可以自由切换。</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="low"
    alt="image"
    src="https://user-images.githubusercontent.com/2854276/234154957-dab73e59-5526-40bd-a1be-8e5ebdf0f103.png"
    ></figure>
<p>当然你也可以继续用<code>xrandr</code>在命令行切换当前显示器的刷新率：</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">xrandr --output eDP-1 --mode <span class="s2">"2560x1600_165.00"</span>
</span></span><span class="line"><span class="cl">xrandr --output eDP-1 --mode <span class="s2">"2560x1600_60.00"</span></span></span></code></pre></div></div>
<p>以上临时注入的配置在重启以后就会消失，Archlinux Wiki 里贴心的写了持久化方案，也就是把配置写到 xorg 文件里。作为懒癌患者，因为偶尔还有不插电的使用场景，所以当然是要搞成自动挡啦：插电 165、电池 60。那么就有两个问题需要解决：</p>
<ol>
<li>插电、离电条件触发</li>
<li>写个切换分辨率的脚本</li>
</ol>
<p>KDE 的系统配置==》电源管理==》节能==》（交流供电、电池供电）运行脚本刚好可以解决脚本触发条件的问题，接下来就是上脚本了：</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="cp">#!/usr/bin/env bash
</span></span></span><span class="line"><span class="cl"><span class="nv">intern</span><span class="o">=</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s2">" connected"</span> <span class="p">|</span> grep <span class="s2">"eDP"</span> <span class="p">|</span> cut -d<span class="s2">" "</span> -f1<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">resolution</span><span class="o">=</span><span class="s2">"2560x1600"</span>
</span></span><span class="line"><span class="cl"><span class="nv">low_mode</span><span class="o">=</span><span class="s2">"</span><span class="si">${</span><span class="nv">resolution</span><span class="si">}</span><span class="s2">_60.00"</span>
</span></span><span class="line"><span class="cl"><span class="nv">high_mode</span><span class="o">=</span><span class="s2">"</span><span class="si">${</span><span class="nv">resolution</span><span class="si">}</span><span class="s2">_165.00"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">function</span> add_mode <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep -E -c <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span><span class="k">)</span><span class="s2">"</span> -eq <span class="m">0</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">==</span> <span class="s2">"</span><span class="nv">$low_mode</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">            xrandr --newmode <span class="nv">$low_mode</span> 282.7 <span class="m">2560</span> <span class="m">2608</span> <span class="m">2640</span> <span class="m">2720</span> <span class="m">1600</span> <span class="m">1603</span> <span class="m">1609</span> <span class="m">1732</span> -HSync -VSync
</span></span><span class="line"><span class="cl">            xrandr --addmode <span class="s2">"</span><span class="nv">$intern</span><span class="s2">"</span> <span class="nv">$low_mode</span>
</span></span><span class="line"><span class="cl">        <span class="k">elif</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">==</span> <span class="s2">"</span><span class="nv">$high_mode</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">            xrandr --newmode <span class="nv">$high_mode</span> 777.410 <span class="m">2560</span> <span class="m">2608</span> <span class="m">2640</span> <span class="m">2720</span> <span class="m">1600</span> <span class="m">1603</span> <span class="m">1609</span> <span class="m">1732</span> -HSync -VSync
</span></span><span class="line"><span class="cl">            xrandr --addmode <span class="s2">"</span><span class="nv">$intern</span><span class="s2">"</span> <span class="nv">$high_mode</span>
</span></span><span class="line"><span class="cl">        <span class="k">fi</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">function</span> change_fps <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">==</span> <span class="s2">"low"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        add_mode <span class="s2">"</span><span class="nv">$low_mode</span><span class="s2">"</span>
</span></span><span class="line"><span class="cl">        xrandr --output <span class="s2">"</span><span class="nv">$intern</span><span class="s2">"</span> --mode <span class="nv">$low_mode</span>
</span></span><span class="line"><span class="cl">    <span class="k">elif</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">==</span> <span class="s2">"high"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">        add_mode <span class="s2">"</span><span class="nv">$high_mode</span><span class="s2">"</span>
</span></span><span class="line"><span class="cl">        xrandr --output <span class="s2">"</span><span class="nv">$intern</span><span class="s2">"</span> --mode <span class="nv">$high_mode</span>
</span></span><span class="line"><span class="cl">    <span class="k">fi</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$#</span><span class="s2">"</span> -eq <span class="m">0</span> <span class="o">]</span> <span class="o">||</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">==</span> <span class="s2">"-h"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> <span class="s2">"Usage: </span><span class="nv">$0</span><span class="s2"> [low|high]"</span>
</span></span><span class="line"><span class="cl">    <span class="nb">exit</span> <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span><span class="line"><span class="cl">change_fps <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span></span></span></code></pre></div></div>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl"># NOTE: I am not responsible for any expired content.
</span></span><span class="line"><span class="cl">create@2023-04-25T02:40:04+08:00
</span></span><span class="line"><span class="cl">update@2023-05-08T05:52:52+08:00
</span></span><span class="line"><span class="cl">comment@https://github.com/ferstar/blog/issues/76</span></span></code></pre></div></div>
]]></content:encoded>
      
    </item>
    
    <item>
      <title>Linux触控板手势增强之「三指拖拽」</title>
      <link>https://blog.ferstar.org/posts/linux-touchpad-gestures-drag/</link>
      <pubDate>Sun, 29 Jan 2023 02:08:34 +0800</pubDate>
      
      <guid isPermaLink="true">https://blog.ferstar.org/posts/linux-touchpad-gestures-drag/</guid>
      <description>在 Linux 上找回 macOS 丝滑的“三指拖拽”体验！基于 Rust 实现的高性能 libinput 手势增强方案，支持 X11 与 Wayland，CPU 占用不到 1% 且配置灵活。</description><content:encoded><![CDATA[<p>转用 Linux 后一直都比较怀念 macOS 上丝滑的<strong>三指拖拽</strong>效果，鉴于近几年出的 Windows 本子触控板面积以及跟手性肉眼可见的改善了很多，我觉得是时候在 Linux 上折腾下<strong>触控板手势</strong>了。</p>
<p>After switching to Linux, I’ve been missing the smooth <strong>three-finger drag</strong> experience from macOS. Given that recent Windows laptops have significantly improved touchpad size and responsiveness, I decided it was time to tackle <strong>touchpad gestures</strong> on Linux.</p>
<hr>

<h2 class="relative group">调研与选型 / Research and Selection
    <div id="调研与选型--research-and-selection" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%b0%83%e7%a0%94%e4%b8%8e%e9%80%89%e5%9e%8b--research-and-selection" aria-label="锚点">#</a>
    </span>
    
</h2>
<p>基本上就是两种实现思路：</p>
<ol>
<li>解析 <code>libinput debug-events</code> 输出，判断手势进而借用类似 <code>xdotool</code> 之类的工具发送具体的键盘组合或者鼠标点击或位移指令。</li>
<li>直接调用 <code>libinput</code> API，明显此方法性能最优。</li>
</ol>
<hr>

<h2 class="relative group">实现方案 / Implementation Approach
    <div id="实现方案--implementation-approach" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%ae%9e%e7%8e%b0%e6%96%b9%e6%a1%88--implementation-approach" aria-label="锚点">#</a>
    </span>
    
</h2>
<p>我选择了一个 Rust <a href="https://github.com/riley-martin/gestures"  target="_blank" rel="noreferrer">实现</a>开抄，负责实现 API 级别的触控手势识别，然后缝合了另一个 Rust <a href="https://github.com/marsqing/libinput-three-finger-drag"  target="_blank" rel="noreferrer">实现</a>，负责实现 API 级别的<strong>拖拽</strong>效果。</p>

<h3 class="relative group">架构逻辑 / Architectural Logic
    <div id="架构逻辑--architectural-logic" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%9e%b6%e6%9e%84%e9%80%bb%e8%be%91--architectural-logic" aria-label="锚点">#</a>
    </span>
    
</h3>
<pre class="not-prose mermaid">graph TD
    A[Touchpad Event] --> B{libinput}
    B --> C[ferstar/gestures <br/>Rust Engine]
    C --> D{Display Server}
    D -- X11 --> E[libxdo API]
    D -- Wayland --> F[ydotool daemon]
    E --> G[Smooth Drag / Key Stroke]
    F --> G
    
    style C fill:#f96,stroke:#333,stroke-width:2px
    style G fill:#4ecdc4,stroke:#333,stroke-width:2px</pre>
<p>目前项目已发展到 <strong>v0.8.1</strong> 版本，主要改进包括：</p>
<ul>
<li><strong>双平台支持</strong>：同时支持 X11 和 Wayland（自动检测）</li>
<li><strong>性能优化</strong>：
<ul>
<li>X11 直接使用 libxdo API，延迟最小</li>
<li>Wayland 优化 ydotool 集成，60 FPS 节流</li>
<li>4 线程池防止 PID 耗尽</li>
<li>正则缓存（once_cell::Lazy）</li>
<li>事件缓存（1秒）减少配置查找</li>
</ul>
</li>
</ul>
<hr>

<h2 class="relative group">性能表现 / Performance Metrics
    <div id="性能表现--performance-metrics" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%80%a7%e8%83%bd%e8%a1%a8%e7%8e%b0--performance-metrics" aria-label="锚点">#</a>
    </span>
    
</h2>
<ol>
<li>
<p><strong>CPU 占用极低</strong></p>
<ul>
<li>极限情况：疯狂三指拖拽某窗口，本 fork 实现 CPU 占用不到 1%</li>
<li>原实现 5~10%</li>
<li>Python、Ruby 等实现 20%+</li>
</ul>
</li>
<li>
<p><strong>资源占用</strong></p>
<ul>
<li>内存占用不到 5MB</li>
<li>程序体积不到 2MB</li>
<li>无多余依赖</li>
</ul>
</li>
</ol>
<hr>

<h2 class="relative group">安装使用 / Installation & Usage
    <div id="安装使用--installation--usage" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%ae%89%e8%a3%85%e4%bd%bf%e7%94%a8--installation--usage" aria-label="锚点">#</a>
    </span>
    
</h2>

<h3 class="relative group">依赖安装 / Install Dependencies
    <div id="依赖安装--install-dependencies" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e4%be%9d%e8%b5%96%e5%ae%89%e8%a3%85--install-dependencies" aria-label="锚点">#</a>
    </span>
    
</h3>
<p><strong>Ubuntu/Debian:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt install libudev-dev libinput-dev libxdo-dev xdotool
</span></span><span class="line"><span class="cl"><span class="c1"># Wayland 需要额外安装</span>
</span></span><span class="line"><span class="cl">sudo apt install ydotool</span></span></code></pre></div></div>
<p><strong>Arch Linux:</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo pacman -S libinput xdotool
</span></span><span class="line"><span class="cl"><span class="c1"># Wayland</span>
</span></span><span class="line"><span class="cl">yay -S ydotool</span></span></code></pre></div></div>

<h3 class="relative group">安装程序 / Install Binary
    <div id="安装程序--install-binary" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%ae%89%e8%a3%85%e7%a8%8b%e5%ba%8f--install-binary" aria-label="锚点">#</a>
    </span>
    
</h3>
<p><strong>方法 1：直接下载预编译二进制</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 从 Releases 下载最新版本</span>
</span></span><span class="line"><span class="cl">wget https://github.com/ferstar/gestures/releases/latest/download/gestures
</span></span><span class="line"><span class="cl">chmod +x gestures
</span></span><span class="line"><span class="cl">sudo mv gestures /usr/local/bin/</span></span></code></pre></div></div>
<p><strong>方法 2：Cargo 安装</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">cargo install --git https://github.com/ferstar/gestures.git</span></span></code></pre></div></div>
<hr>

<h2 class="relative group">配置说明 / Configuration
    <div id="配置说明--configuration" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%85%8d%e7%bd%ae%e8%af%b4%e6%98%8e--configuration" aria-label="锚点">#</a>
    </span>
    
</h2>
<p>配置文件使用 KDL 格式，示例：</p>
<div class="highlight-wrapper"><pre tabindex="0"><code class="language-kdl" data-lang="kdl">// 三指拖拽（X11 & Wayland 通用）
gesture "drag" swipe any {
    fingers 3
    acceleration 1.0      // 拖拽速度
    mouse_up_delay 500    // 抬手后延迟（ms）
}

// 四指上滑切换工作区
gesture "switch-workspace-up" swipe up {
    fingers 4
    exec "xdotool" "key" "super+Page_Up"
}</code></pre></div>
<hr>

<h2 class="relative group">运行程序 / Running the Program
    <div id="运行程序--running-the-program" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e8%bf%90%e8%a1%8c%e7%a8%8b%e5%ba%8f--running-the-program" aria-label="锚点">#</a>
    </span>
    
</h2>

<h3 class="relative group">Systemd 服务（推荐）/ Systemd Service (Recommended)
    <div id="systemd-服务推荐-systemd-service-recommended" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#systemd-%e6%9c%8d%e5%8a%a1%e6%8e%a8%e8%8d%90-systemd-service-recommended" aria-label="锚点">#</a>
    </span>
    
</h3>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 安装服务文件</span>
</span></span><span class="line"><span class="cl">gestures install-service
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 启动并设为开机自启</span>
</span></span><span class="line"><span class="cl">systemctl --user <span class="nb">enable</span> --now gestures</span></span></code></pre></div></div>
<hr>

<h2 class="relative group">常见问题 / Common Issues
    <div id="常见问题--common-issues" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e5%b8%b8%e8%a7%81%e9%97%ae%e9%a2%98--common-issues" aria-label="锚点">#</a>
    </span>
    
</h2>

<h3 class="relative group">权限问题 / Permission Issues
    <div id="权限问题--permission-issues" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e6%9d%83%e9%99%90%e9%97%ae%e9%a2%98--permission-issues" aria-label="锚点">#</a>
    </span>
    
</h3>
<p>需要将用户加入 <code>input</code> 组：</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo usermod -aG input <span class="nv">$USER</span></span></span></code></pre></div></div>
<hr>

<h2 class="relative group">项目链接 / Project Links
    <div id="项目链接--project-links" class="anchor"></div>
    
    <span
        class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none">
        <a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#%e9%a1%b9%e7%9b%ae%e9%93%be%e6%8e%a5--project-links" aria-label="锚点">#</a>
    </span>
    
</h2>
<ul>
<li><strong>GitHub</strong>: <a href="https://github.com/ferstar/gestures"  target="_blank" rel="noreferrer">https://github.com/ferstar/gestures</a></li>
<li><strong>最新发布</strong>: <a href="https://github.com/ferstar/gestures/releases"  target="_blank" rel="noreferrer">https://github.com/ferstar/gestures/releases</a></li>
<li><strong>问题反馈</strong>: <a href="https://github.com/ferstar/gestures/issues"  target="_blank" rel="noreferrer">https://github.com/ferstar/gestures/issues</a></li>
</ul>
<hr>
<p><strong>Enjoy!</strong></p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="nx">NOTE</span><span class="o">:</span> <span class="nx">I</span> <span class="nx">am</span> <span class="nx">not</span> <span class="nx">responsible</span> <span class="k">for</span> <span class="nx">any</span> <span class="nx">expired</span> <span class="nx">content</span><span class="p">.</span>
</span></span><span class="line"><span class="cl"><span class="nx">Created</span> <span class="nx">at</span><span class="o">:</span> <span class="mi">2023</span><span class="o">-</span><span class="mi">01</span><span class="o">-</span><span class="mi">29</span><span class="nx">T02</span><span class="o">:</span><span class="mi">08</span><span class="o">:</span><span class="mi">34</span><span class="o">+</span><span class="mi">08</span><span class="o">:</span><span class="mi">00</span>
</span></span><span class="line"><span class="cl"><span class="nx">Updated</span> <span class="nx">at</span><span class="o">:</span> <span class="mi">2026</span><span class="o">-</span><span class="mi">01</span><span class="o">-</span><span class="mi">04</span><span class="nx">T06</span><span class="o">:</span><span class="mi">00</span><span class="o">:</span><span class="mi">00</span><span class="o">+</span><span class="mi">08</span><span class="o">:</span><span class="mi">00</span>
</span></span><span class="line"><span class="cl"><span class="nx">comment</span><span class="err">@</span><span class="nx">https</span><span class="o">:</span><span class="c1">//github.com/ferstar/blog/issues/73
</span></span></span></code></pre></div></div>
]]></content:encoded>
      
    </item>
    
  </channel>
</rss>
