# 04 · 桌宠窗口使用 桌宠窗口是 EzVibeR+ 的主界面:一个**透明、置顶、可缩放**的小窗,里面有 Live2D 模型 + 右侧聊天面板。 ## 1. 窗口特性 | 特性 | 行为 | |---|---| | 透明 | 背景完全透明,只有模型本身看得见 | | 始终置顶 | 在所有应用之上 | | 所有工作区可见 | 切换虚拟桌面时仍跟着你 | | 不在任务栏显示 | 任务栏不会出现图标,只能从系统托盘进 | | 可调整大小 | 拖窗口边缘,最小 555×280,最大 800×640 | | 位置记忆 | 移动/缩放后位置和尺寸自动存盘(`live2d.conf.json`) | | 禁双击最大化 | 透明窗口的双击被拦截,不会被窗口管理器意外全屏化 | ### 1.1 调整窗口大小 1. 点工具栏 **⬚ 大小** 按钮(倒数第 4 个)— 窗口边缘会变成虚线,进入可调整状态 2. 鼠标拖边缘/角,调到合适大小 3. 失焦后自动退出调整模式 ### 1.2 移动窗口 1. 点工具栏 **📍 位置** 按钮(中间)— 模型上叠加一个 drag region 2. 直接拖模型本体即可 3. 再点 **📍 位置** 退出移动模式 > 也可以直接拖**模型上方 35% 的区域**(即"头部") — 但这会切到下一个表情,不是移动。 ### 1.3 隐藏/恢复 - **隐藏**:右键托盘 → 「隐藏桌宠」 / 点工具栏 **❌ 关闭** 按钮(隐藏后 1.3 秒) - **恢复**:右键托盘 → 「显示桌宠」 ## 2. 浮动工具栏(9 个按钮) 桌宠窗口**右侧**有一个半透明白底竖排工具栏,从上到下: | # | 图标 | 含义 | 操作 | |---|---|---|---| | 1 | 💬 | **聊天面板切换** | 展开/收起右侧聊天面板(收起后模型占满整个窗口) | | 2 | ⚙ | **配置** | 打开「配置中心」窗口(独立窗口,可关) | | 3 | ☐ | **背景遮罩** | 给桌宠背景加 20% 灰底(视觉辅助,可关) | | 4 | 👁 | **换模型** | 随机换一个模型 | | 5 | 📍 | **位置移动** | 进入/退出"拖拽移动"模式(蓝色高亮表示激活) | | 6 | ⬚ | **调整大小** | 让窗口边缘变虚线可调 | | 7 | ⓘ | **复制模型 URL** | 把当前模型地址复制到剪贴板(可粘贴到浏览器看) | | 8 | 🔒 | **鼠标穿透** | 开启后鼠标点穿桌宠到下面的应用(**谨慎**:开了就点不到桌宠了,要右键托盘恢复) | | 9 | ❌ | **关闭桌宠** | 隐藏窗口(不退出应用,托盘还在) | > 💡 鼠标悬停每个按钮都有 tooltip 提示。 ## 3. 与模型互动 ### 3.1 鼠标点击模型 | 点击位置 | 反应 | |---|---| | **头部**(模型上方 35%) | 切换到下一个表情(循环) | | **身体**(其余 75%) | 播放一个随机动作 + 触发"用户互动"情绪事件 + 截图 | > **点击身体**会同时触发**两件事**: > 1. 播放动作(`tap_body` / `TapBody` / `Tap` / `tap` 之一,从你模型自带的动作里选第一个匹配的) > 2. **触发全屏截图** — 详见 §4 ### 3.2 鼠标双击 **双击不会**最大化(已禁掉),但也**不**有别的特殊功能。 ### 3.3 键盘(仅在"位置移动"模式下) 按住 **Shift** 的同时: - **`+`**(数字键盘 `+` 或主键盘 `=`):放大模型 1% - **`-`**(数字键盘 `-` 或主键盘 `_`):缩小模型 1% > 缩放比例会随每个模型单独存盘。 ## 4. 截图 → AI 点桌宠**身体** → **整屏截图**自动进入聊天面板。 ### 4.1 流程 1. 桌宠窗口**隐藏**(避免截到模型自己) 2. 后端调系统截图能力(Linux: `xdg-desktop-portal` → `convert` 回退;macOS/Windows: 系统能力) 3. 桌宠窗口**恢复**显示 + 拿回焦点 + 恢复置顶(这一系列动作全自动) 4. 聊天面板右侧出现一个**预览气泡**,里面是截图缩略图 + 一个输入框 + 两个按钮 ### 4.2 预览气泡三个状态 | 状态 | 行为 | |---|---| | 在聊天流里 | 等待你输入或操作(**不持久化**:reboot 后会自动消失) | | 输入了文字 + 点 **"发送给AI"** | 截图 + 文字以"user"消息身份发出,AI 回复;气泡**立即消失** | | 直接点 **"取消"** | 气泡**立即消失**,不发送任何东西 | > ⚠️ **截图预览气泡不会被存盘**。即使你在 250 ms 内连续操作(移除 + 重新添加),也保证不写入 jsonl 聊天记录(前端清理 debounce timer + 后端拒绝写入 + reload 跳过读出三层防御)。 ### 4.3 截图保存位置 截图原图 + 压缩预览存在 `/sessions/<当前会话 id>/images/.{png,jpg}`,消息里只存路径不存 base64(节省内存)。 > 启动时会自动跑 GC,把磁盘上没人引用的孤儿 PNG/JPG 删掉,**不会删你正在用的**。日志里会打印"扫描/引用/删除/释放字节"统计。 ## 5. 情绪引擎 桌宠有 5 种情绪状态,**所有状态都对应 Live2D 动作 + 表情**(如果你的模型有的话): | 状态 | 中文 | 触发条件 | 默认动作 | 默认表情关键词 | |---|---|---|---|---| | **Idle** | 空闲 | 启动默认 / 长时间无互动 | `idle` | (无) | | **Happy** | 开心 | 点击身体、收到对话、点"赞"按钮 | `happy` | 星星/比耶/happy/smile | | **Focused** | 专注 | 点"专注模式"或类似 | `focused` | 照相/serious/focus | | **Annoyed** | 烦躁 | 忽略提醒、久坐超时 | `angry` | 黑脸/流汗/angry | | **Sleepy** | 困倦 | 长时间无互动(每 60 秒一个 TimePasses 事件累计推进) | `sleepy` | 哭/sleepy/tired | ### 5.1 情绪如何驱动 Live2D - **动作匹配** — 按关键词从模型自带的 motion 列表里找(精确 → 包含 → 反向包含),找不到就用第一个 - **表情匹配** — 按关键词从模型自带的 expression 列表里找(中文优先),找不到就保持当前 - **没模型或模型没这些动作/表情** — 静默跳过,控制台打 debug 日志 ### 5.2 心跳 后端每 60 秒发一次 `ezvibe:heartbeat` 事件,前端接收后会做: 1. 更新情绪状态 2. 如果当前是 Idle 且 45 秒内没交互,从当前情绪的"微表情"列表里轮换一个(避免长时静置呆板) ### 5.3 状态最短驻留 切换情绪后**至少停留 5 秒**,避免连续事件导致的"闪烁"。这是情绪引擎的内部保护,不可关闭。 ## 6. 键盘焦点问题(Linux 已知) 如果你发现聊天面板"卡住"点不动: - 大概率是窗口管理器(GNOME mutter / KDE)在某些操作后把焦点丢了 - 一般重新点一下桌宠窗口内部任意位置就能拿回焦点 - 截图后会自动 `set_focus()` 恢复(**截图后丢失焦点是已知问题**) --- 下一步:[05-聊天功能.md](05-聊天功能.md) — 多会话、搜索、导出、提醒中心。