- AI 插件
- dsh-plugin
- 交互助手
- 桌面应用
【免费下载链接】dsh-pet
DSH 桌面宠物:一行命令装好即用的透明动画小桌宠,支持多开、大小位置随心配置;还内置 DIY 素材链,能用 AI 视频自造专属宠物
dsh-pet 是一个一行命令装好即用的透明动画桌面宠物(桌宠)项目:支持多开、大小位置随心配置,还能把宠物甩出去看它跨屏弹跳。但多屏 + 不同 DPI 缩放的 Windows 桌面上,普通做法的宠物会"分身闪烁"、甚至飞进没有显示器的"虚空"里消失。本文带你搞懂 dsh-pet 是如何用「全局 DPI 线性化 + 逐屏 AABB 抛掷空间 + 跨屏放行判定」三件套,让桌宠在任何屏幕布局下都不乱飞。
一、先搞清楚问题:两块不同缩放的屏发生了什么
在 Windows 上,Chromium 的 DIP(设备无关像素)↔ 物理像素换算是逐显示器的仿射变换:窗口"归属"在哪块屏,就用哪块屏的缩放参数换算。窗口骑在屏缝上时归属会反复翻转——两屏缩放不同时,同一个 DIP 坐标翻转前后会落到不同物理位置。
dsh-pet 用探针脚本 tools/probe-dpi.cjs 在 1.5 + 1.75 双屏上实测:
- 位置差110px,924 DIP 宽的窗口尺寸差231px
- 结果就是拖过屏缝时宠物"分身闪烁",每帧落点在两套坐标系之间横跳
二、第一步:全局 DPI 线性化,让所有屏说同一种"像素"
dsh-pet 的修法是启动前强制--force-device-scale-factor=1,把所有屏塌缩成同一个恒等映射,再按探测到的真实主屏缩放把宠物放大回原来的观感——即"线性化 + 补偿"两步:
| 步骤 | 做什么 | 效果 |
|---|---|---|
| 线性化 | 强制 device scale factor = 1 | DIP = 物理像素,跨屏几何再无换算与舍入 |
| 补偿 | 渲染端CONFIG.scale× 真实主屏缩放 | 主屏观感与修复前逐像素一致 |
为什么必须锁死为 1 而不是主屏的 1.5?实测发现取 1.5 会触发二次缩放 bug:主屏 3840 物理像素宽被报成 1706,而同一块屏的 workArea 却报 2560,两者自相矛盾,副屏多出 1281px 的恒定偏移——比不修还糟。
这条"要不要启用 / 强制成几 / 渲染端乘几"的规则被抽成了纯函数 dsh-pet/runtime/electron-helper/dpi-linearization.js,不依赖 Electron、可被node:test直接单测锁定。多屏几何的完整推理与取值时机(探测子进程、缓存落盘)见 dsh-pet/runtime/electron-helper/main.js 的长注释。
三、桌面几何:用"工作区并集"而不是一个外接大矩形
DPI 修好之后,多屏布局本身还是个大坑。dsh-pet 把桌面建模为工作区矩形的并集,而不是所有屏的外接矩形(hull):
外接矩形在屏幕摆放不规则时会出现大片不属于任何显示器的空洞。以外接矩形为边界的漫游/抛掷/角落定位会把宠物放进空洞里——用户完全看不到它。实测一例"右倒 T 型"双屏:外接矩形 23.7% 的面积是空洞。
核心几何工具集中在 dsh-pet/src/shared/displays.ts,包括:
boundingRect:外接矩形,仅作坐标系原点与换算基准rectAtPoint/indexAtPoint:点被哪块屏覆盖nearestIndex+clampPointToRegion:宠物落在空洞里(拔屏、改分辨率后)时把它拉回最近的那块屏
主进程用screen.getAllDisplays()采集逐屏 workArea(areas)+ 逐屏完整面板(panels,含任务栏区),连同主屏下标一起推送给渲染端,见 dsh-pet/runtime/electron-helper/main.js 的deskGeometry()。漫游选点、角落定位同样改判并集——dsh-pet/src/shared/motion.ts 的角落定位就特意取"那块屏"而不是外接矩形,否则 T 型布局的左上角可能压根不在任何显示器上,宠物开机即隐身。
四、逐屏 AABB 抛掷空间:每块屏一套边界
这是"不乱飞"的核心数据结构ThrowSpace,定义在 dsh-pet/src/shared/physics.ts:
| 字段 | 含义 | 用途 |
|---|---|---|
bounds | 逐屏的包围盒左上角允许范围(每屏一套 AABB) | 反弹边界 |
areas | 逐屏工作区(任务栏把面板挖掉的条带不含在内) | 归属判定、反弹/休息线 |
panels | 逐屏完整面板(含任务栏区) | 越界侧"有没有邻屏"探测 |
size/sideAllow | 宠物包围盒宽 / 身体左右内缩量 | 让"身体"贴边而不是"视频盒"贴边 |
单块屏时,它退化等价于传统的一个大 AABB;多块屏时,每块屏都有自己的一圈边界,宠物永远不可能被夹进空洞。
五、跨屏放行判定:越界那一刻,先看缝外有没有屏
关键步进函数是 dsh-pet/src/shared/physics.ts 的throwStepRegion。它与单屏版throwStep共用同一套重力 / 反弹 / 摩擦物理,唯一区别是:
- 边界取自"身体中心所在屏"的 AABB,而不是整个桌面;
- 越界后多问一句:"越出去的那一侧到底有没有屏?"探测点取该边外第一像素、另一轴取身体中心:
- 那里有别的屏 ⇒原样放行(不夹不弹),宠物自然跨屏飞行、落到下一块屏;
- 那里什么都没有 ⇒ 按该边反弹。这正是外接矩形方案缺的那道墙。
三个容易翻车的细节它都处理了:
- 任务栏条带不是墙:探测目标用完整面板(
panels)而不是工作区。任务栏卡在上下两块屏的接缝处时,两块 workArea 之间会隔一条"不属于任何屏"的条带——按工作区探测会把它当墙,宠物永远穿不过上下叠放的屏。 - 无状态判定:放行时不改位置、也不记录"当前屏",下一帧照样由身体中心重新定位。若改成"越界即切屏",相邻两屏 AABB 在缝隙处留有 2×sideAllow 的重叠盲区,骑缝的宠物会在两屏之间逐帧对跳。
- 屏幕拔插容错:飞行途中屏数变少时,锁定屏索引越界即自动退回不锁定,避免拿一块不存在的屏当边界。
六、不想跨屏?一个开关把屏缝变成墙
多屏用户如果更希望宠物"待在本屏",配置根字段confineToScreen设为true即可(见 dsh-pet/assets/config.jsonc):
true= 甩出去的宠物只在松手时所在那块屏幕内弹(屏缝当墙);false(默认)= 屏缝两侧都有屏时照常跨屏飞行、落到隔壁屏。
它的实现极简:throwStepRegion多传一个lockScreen ≥ 0,边界恒取该屏 AABB、两条轴的邻屏探测一律跳过——屏缝与空洞一样当墙。而"锁不锁定"不改任何手感参数(重力/弹性/力度),只改宠物被允许去哪,所以它被刻意放在配置根字段而不是physics段。
七、macOS 例外与可单测的纯函数设计
DPI 线性化在 macOS 上一律不启用(shouldLinearize对darwin返回 false):macOS 的 DIP 恒等于"点",force-device-scale-factor只改 backing store 分辨率、不改坐标系,没有可补偿的东西——实测同一台机器开关两种状态下workArea完全一致。若强行补偿,配置 size=462 的宠物会被渲染成 924 点宽,整个窗口比 1080p 屏幕还高,直接被顶到屏幕中央。
这套机制的工程质量也很值得新手参考:判定规则全是纯函数(不 require electron、不读环境变量、不碰文件系统),配合 dsh-pet/src/shared/physics.ts 的单测,单屏退化行为、多屏放行/反弹、空洞边界都被逐位钉住——单块屏时探测点恒无邻屏、恒反弹,与传统单屏实现逐位一致。
小结
dsh-pet 的"不乱飞"本质上是三道防线:
- 全局 DPI 线性化:强制 scale=1 消除逐屏仿射变换的横跳,再按主屏缩放补偿观感;
- 工作区并集 + 逐屏 AABB:边界判定永远以"屏"为单位,空洞天然成墙;
- 无状态跨屏放行判定:越界那一刻探测缝外有没有屏,有则放行、无则反弹,屏缝两侧有屏恒放行,跨屏弹跳手感不减。
三招组合下来,无论你的屏是横排、竖叠还是右倒 T 型,宠物都只会在"看得见的地方"弹跳。
- AI 插件
- dsh-plugin
- 交互助手
- 桌面应用
【免费下载链接】dsh-pet
DSH 桌面宠物:一行命令装好即用的透明动画小桌宠,支持多开、大小位置随心配置;还内置 DIY 素材链,能用 AI 视频自造专属宠物
相关推荐
一行命令让蓝鲸住进你的屏幕:dsh-pet 桌面宠物5分钟快速上手教程
一行命令让蓝鲸住进你的屏幕:dsh pet 桌面宠物5分钟快速上手教程 dsh pet 是一款一行命令即可安装的 DSH 桌面宠物插件:透明动画小桌宠装好即用,
AI 插件dsh-plugin交互助手桌面应用Deskreen: 打造你的多屏工作空间,无处不在
Deskreen: 打造你的多屏工作空间,无处不在 是一个轻量级且跨平台的应用,它能把任何设备变成你的第二(或第三、第四)显示器,通过网络连接实现远程扩展桌面的
桌面应用音视频鸿蒙跨设备投屏实战:打破空间限制的屏幕共享新体验
鸿蒙跨设备投屏实战:打破空间限制的屏幕共享新体验 你是否曾经遇到过这样的困境:想要在电脑大屏上演示手机应用,却只能通过繁琐的截图和传输;或者作为开发者需要调试鸿
开发工具音视频OpenHarmony
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考