正式开源! Penio

Penio 是一款基于 Tauri 开发的录屏辅助工具,提供鼠标点击特效、键盘回显和屏幕标注功能,支持 Windows/macOS/Linux 跨平台。本文分享从商业化到开源的决策历程,以及 Tauri 开发中窗口透明、系统权限、跨平台适配等实战经验与踩坑总结。

- 次阅读 1,072 字 阅读约 4 分钟

前言

在写Penio之前,我有使用过类似的工具,如ppink,presentify但是发现总是有一些地方,我不太满意,正好那会对tauri开发比较干兴趣,所以自己就决定开发了,最开始是准备商业化的,但是发现很少有人愿意付费,所以就干脆开源出来,让更多的用户能够使用

功能介绍

鼠标特效

最开始的时候,Penio只有给鼠标添加点击动画的功能

键盘回显

不过随着迭代,我又给Penio添加了键盘回显,方便在视频中显示快捷键操作

屏幕标注

在屏幕中想要标注一些重要的地方时,又添加了屏幕标注功能

Note

屏幕标注基于excalidraw开发,集成的效果非常好,手绘风格与教学视频也非常契合

跨平台

Penio使用了跨平台开发框架-tauri,所以可以同时在windows、macos、linux(x11)上使用

开发记录

App图标

Note

图标我是直接使用Inkscape,基于iconfont上的图标修改得到

一个笔的形状,代表了Penio的屏幕画笔核心功能

Penio图标

窗口透明

在tauri中实现窗口透明非常简单,只需要设置transparent: true即可

Warning

macos,需要设置macOSPrivateApi=true,才能使用transparent api。

let window = tauri::WebviewWindowBuilder::new(
        app,
        &window_label,
        tauri::WebviewUrl::App("/motion-board.html".into()),
    )
    .title(&format!("Motion Board {}", index))
    .inner_size(800.0, 600.0)
    .transparent(true)

我们也可以在tauri.conf.json中设置transparent=true

{
  "app": {
    "macOSPrivateApi": true,
    "windows": [
      {
        "title": "...",
        "transparent": true,
        ...
      }
    ]
  }
}

窗口无边框

其实在使用tauri开发的过程中,并非一帆风顺,尤其是tauri中的api在不同系统上的表现不一样

比如,我想要实现窗口全屏+无边框效果

#[cfg(target_os = "windows")]
{
  // decorations本来是控制窗口边框的, 但是这里必须设置为true
  // 否则会在顶部出现奇怪的幽灵标题栏
  window.set_decorations(true).unwrap();
  window.set_fullscreen(true).unwrap();
}

#[cfg(target_os = "macos")]
{
  //而在macos上则需要设置为false才行
  window.set_decorations(false).unwrap();

  // 特别坑的地方!!!
  // 1. macos不能使用set_fullscreen全屏,否则会同时创建虚拟桌面,让窗口独占一个桌面
  // 2. macos不能使用maximize最大化,否则窗口将无法移动
  // 3. 只能通过设置窗口大小为屏幕大小来实现全屏
  let size = monitor.size();
  window
    .set_size(
      tauri::PhysicalSize::new(
          size.width as f64,
          size.height as f64,
      ))
    .unwrap();
}

JS创建窗口

在tauri中,必须将command声明为async来创建窗口,否则会让整个应用阻塞住


// 必须带上async关键字, 否则当前端调用命令时会直接阻塞整个应用
#[tauri::command]
async fn refresh_monitors(app: AppHandle, emit_event: bool) -> Result<(), String> {
   // ... 创建窗口的代码
}

// 不能这样写!!!
#[tauri::command]
fn refresh_monitors(app: AppHandle, emit_event: bool) -> Result<(), String> {
   // ...
}

屏幕像素单位

如果你想要在tauri中获取屏幕的大小,你必须要知道tauri在不同平台上单位的区别

  • windows是物理像素单位

  • macos是逻辑像素单位

  • linux是物理像素单位

macos系统权限

macos系统对应用的权限控制非常严格,一开始我在调试的时候,发现怎么都无法捕获鼠标和键盘的事件,后面才明白需要在系统设置中给应用添加辅助功能和输入监控权限,才可以正常使用全局的鼠标和键盘事件监听功能

macos权限设置

x11系统适配

当我在linux x11系统上测试时候,发现应用会崩溃,会提示如下报错

[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
penio: ../../src/xcb_io.c:274: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
Aborted

这是因为在x11系统上,我们需要在程序开头调用XInitThreads()

解决方法

  1. 首先在Cargo.toml中添加x11包

    [target.'cfg(target_os = "linux")'.dependencies]
    x11 = "2.21.0"
    
  2. 然后在main.rs中调用XInitThreads()

    fn main() {
        #[cfg(target_os = "linux")]
        {
            use x11;
            unsafe {
                x11::xlib::XInitThreads();
            }
        }
       
        if let Err(e) = penio_lib::run() {
            eprintln!("Error running application: {}", e);
            std::process::exit(1);
        }
    }
    

发布记录

windows

MSIX自启动

打包windows应用时,我选择了msix格式,这样可以省去购买ov签名的费用,同时不需要自己托管安装包的下载。 不过msix打包tauri应用的时候,我发现tauri-autostart插件无法正常生效,需要手动在程序清单文件中加入微软官方的自启动插件

<Package 
  ...
  xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10">

  <Application>
    <Extensions>
        <desktop:Extension Category="windows.startupTask" Executable="Penio.exe" EntryPoint="Windows.FullTrustApplication">
          <desktop:StartupTask TaskId="PenioStartupId" Enabled="true" DisplayName="Penio" />
        </desktop:Extension>
    </Extensions>
  </Application>
</Package>

MSIX快捷方式

使用 MSIX Package tool 打包时,程序创建的快捷方式启动会报错

快捷方式报错

我们需要去掉默认的快捷方式扩展。

<Package 
  ...
>

  <Application>
    <Extensions>
        <desktop7:Extension Category="windows.shortcut">
          <desktop7:Shortcut File="[{Desktop}]\Penio.lnk" Icon="[{Package}]\penio.exe" Description="Runs Penio" />
        </desktop7:Extension>
        <desktop7:Extension Category="windows.shortcut">
          <desktop7:Shortcut File="[{Common Programs}]\Penio\Penio.lnk" Icon="[{Package}]\penio.exe" Description="Runs Penio" />
        </desktop7:Extension>
    </Extensions>
  </Application>
</Package>
Tip

如果需要快捷方式,可以将开始菜单的应用快捷方式拖到桌面上

整体总结

总的来说,tauri是一个非常不错的跨平台桌面应用开发框架,虽然开发过程中有一些小的毛病,但是基本都能找到对应的解决方案,如果你是准备找一个能够快速开发,更现代的跨平台框架,我强烈推荐你试试tauri。

除了跨平台外,tauri其他方面也非常优秀

  1. Rust生态的cargo包管理简直不要太方便
  2. tauri 自带标准的 Github Action 工作流,轻易就能实现CI/CD
  3. tauri 官方提供了大量的系统插件(托盘,通知,文件系统等),开箱即用

文档信息


版权: 本文采用 CC-BY-NC-SA 4.0 许可协议
日期: 2026年2月15日 16:43
作者: Game1024