ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

BongoCat Overlay 放置约束演进:从工作区限制到屏幕并集与延迟收敛(ADR-0045 解读与源码剖析)

BongoCat Overlay 放置约束演进:从工作区限制到屏幕并集与延迟收敛(ADR-0045 解读与源码剖析) 桌面应用【免费下载链接】BongoCat BongoCat — A cross-platform interactive desktop pet that brings fun to your desktop!项目地址https://gitcode.com/gh_mirrors/bong/BongoCat点击查看免费下载导读本文围绕 BongoCat 的 ADR-0045Overlay 放置约束改为屏幕范围并延迟收敛展开系统讲解桌面宠物 overlay 窗口从工作区内约束迁移到所有显示器矩形并集 1 秒静止延迟纠正的架构决策、平台适配实现与配置用法。读完你可以掌握keep_inside_screen配置的语义、PLACEMENT_SETTLE_DELAY/PLACEMENT_INSPECTION_INTERVAL两个关键常量的作用以及跨显示器拖拽、任务栏覆盖、显示器热插拔自愈等场景的底层工作原理。一、背景旧的工作区约束为何不符合预期在 v1 版本中overlay 窗口的放置约束由overlay.keep_inside_work_area控制其语义是避开工作区之外的一切区域Windows 用MONITORINFO.rcWork、macOS 用NSScreen.visibleFrame作为约束边界并在窗口创建、需要资源重建的设置/模型重建以及每一次 frame tick 中收敛窗口原点见 docs/adr/0045-overlay-placement-screen-bounds.md 的 Context 章节。这套行为暴露出两类明显不符合用户预期的问题系统栏成为禁区模型窗口无法覆盖任务栏Windows、程序坞 Dock 和菜单栏macOS所在的区域。用户把猫放在任务栏上方这类看起来非常合理的摆放会在下一帧被立刻推回工作区内。收敛过于激进破坏跨屏拖拽收敛在每一个 frame tick 上执行而两个平台的原生拖动循环都会阻塞 frame source——Windows 系统拖动循环、macOS 的 AppKit 窗口拖动都会让会话在指针松开后才能观察到最终矩形。于是拖拽一结束窗口就被拉回最近的显示器。当窗口处于相邻两块显示器的接缝处、或者交叠面积更大的其实是对面的显示器时这一拉回会直接把用户刚拖到的位置抢走导致跨显示器摆放几乎无法完成。二、决策约束区域改为屏幕并集纠正延迟执行ADR-0045 的核心决策可以概括为四点详见 ADR 的 Decision 章节约束区域从某一块显示器的工作区改为所有已连接显示器矩形的并集。Windows 侧取EnumDisplayMonitorsMONITORINFO.rcMonitormacOS 侧取NSScreen.frame。窗口可以覆盖任务栏 / Dock / 菜单栏负坐标位于主显示器左侧或上方的显示器保持有效。判定窗口完整显示的口径是并集覆盖而非落在单块显示器内一个横跨两块显示器、但每一部分都落在某块显示器上的窗口是合法摆放不纠正只有窗口真正越过桌面边界时才纠正。纠正目标是与窗口交叠面积最大的显示器无交叠时取中心距离最近者保持窗口尺寸不变窗口大于显示器时把原点贴到显示器原点与旧行为一致。纠正延迟执行窗口连续静止1sPLACEMENT_SETTLE_DELAY后才移回显示器内期间任何被观测到的位移都重新计时。创建、缩放/资源设置重建和模型重建这些没有拖拽在途的路径仍然立即收敛。同时放置检查最多缓存500msPLACEMENT_INSPECTION_INTERVAL后重新评估既避免了静止窗口每帧枚举显示器macOS 枚举会分配内存、Windows 枚举会调用进窗口管理器又让显示器拓扑变化——包括拔掉外接屏后窗口留在桌面外——在没有平台通知通道的情况下仍能被纠正。字段随语义改名overlay.keep_inside_work_area→overlay.keep_inside_screen。由于当前 v1 尚未发布按 ADR-0054 之前确立的 §4.1 直接改名不引入 alias、迁移或旧键兼容。三、配置与默认值keep_inside_screen新的配置字段定义在 crates/bongocat-config/src/config_schema/overlay.rs属于OverlayConfig结构体/// Keep the overlay window fully on a display. The window stays on /// the union of the connected displays, so it may cover a taskbar, Dock or /// menu bar, and a window dragged off the desktop is moved back only after /// the drag has stopped. This replaces the earlier work-area constraint, /// which forbade the desktop chrome strip entirely. pub keep_inside_screen: bool,默认配置shared/config/fixtures/default.json中该字段为trueoverlay: { click_through: false, always_on_top: true, scale_percent: 100, opacity_percent: 100, hide_on_pointer_hover: false, hide_on_pointer_hover_delay_seconds: 0, keep_inside_screen: true, maximum_fps: 60 }从源码结构可以确认两个使用要点开启时窗口被限制在所有显示器的并集内允许覆盖系统栏越界纠正延迟 1 秒。关闭时约束完全不起作用用户可以把窗口摆到任何位置包括大部分超出桌面之外这取决于平台对窗口矩形的放行程度。另外两个平台的封面捕获会话CoverCaptureSession在创建离屏渲染窗口时会把该字段强制设为false见 crates/bongocat-overlay/src/windows/cover_capture.rs 与 crates/bongocat-overlay/src/macos/cover_capture.rs因为捕获窗口不需要参与放置约束。四、平台无关的放置判定核心placement模块ADR 明确要求逻辑落在平台无关的bongocat-overlay/src/placement模块平台适配器只负责枚举显示器与读写窗口矩形判定与倒计时都可以在没有 GPU 和原生窗口的情况下测试。该模块位于 crates/bongocat-overlay/src/placement.rs是整篇 ADR 落地的最关键代码。4.1 两个常量pub(crate) const PLACEMENT_SETTLE_DELAY: Duration Duration::from_millis(1_000); pub(crate) const PLACEMENT_INSPECTION_INTERVAL: Duration Duration::from_millis(500);源码注释给出了两者精确的取舍逻辑PLACEMENT_SETTLE_DELAY1000ms1 秒足够覆盖一次有意的跨屏拖拽中途的停顿窗口常在跨越途中被松开用户往往会立刻重新抓取又足够短让被拖出桌面的窗口不会长期丢失。由于原生拖动循环会阻塞 frame source会话只能在指针松开后观察到稳定的窗口矩形因此这个延迟永远是拖拽结束后的延迟。PLACEMENT_INSPECTION_INTERVAL500ms刻意短于PLACEMENT_SETTLE_DELAY这样挂起的纠正至少会在截止时间到来前针对当前显示器集合重新评估一次——如果倒计时中途插入了新的显示器纠正会被取消而不是把已经重新合法的窗口移走。4.2 并集覆盖判定bounds_inside_screens该函数回答窗口的每一部分是否都落在某块显示器上。显示器是共享坐标空间中的轴对齐矩形允许重叠或排成 L 形所以在显示器上是关于并集的问题而不是关于单个矩形的问题。算法把窗口在每一个落在窗口内部的显示器边界处切片每个切片内覆盖它的显示器集合恒定切片被覆盖当且仅当窗口的垂直跨度落在这些显示器合并后的垂直跨度内crates/bongocat-overlay/src/placement.rs。值得注意的两个边界情形显示器列表为空时不视为在显示器上但由于此时也找不到任何纠正目标窗口会留在原地调用方不会产生纠正动作。计算统一在无界i64空间中进行window_edges/screen_edges避免显示器坐标接近i32极限时溢出。4.3 纠正目标选择correction_for_screens与nearest_screen纠正目标是与窗口交叠面积最大的显示器交叠相同时取中心距离最近者窗口与任何显示器都无交叠时取中心距离最近者crates/bongocat-overlay/src/placement.rs。源码注释明确指出这与两个平台会话在约束可移植化之前的显示器选择语义完全一致——Windows 之前请求MonitorFromRect(.., MONITOR_DEFAULTTONEAREST)macOS 之前取最大交叠、失败时取最小中心距离。多显示器选择逻辑从此只有一份行为差异只剩平台坐标原点方向AppKit 底部原点、Win32 顶部原点而分类计算对两者等价。OverlayWindowBounds::clamp_tocrates/bongocat-overlay/src/bounds.rs负责不改变尺寸地移动窗口当窗口在某一轴上大于显示器时原点被钳制到显示器自己的原点窗口保持钉在显示器左上角而不是被推到对侧边缘之外。测试 crates/bongocat-overlay/src/tests/bounds.rs 验证了这一行为——尺寸 2400×1200 的窗口在 1920×1080 的显示器上会被钉到(-1920, 0)而保持原尺寸。4.4 延迟纠正状态机OverlayPlacementConstraintOverlayPlacementConstraint::observe是每帧喂入窗口矩形、单调时钟与显示器读取闭包的入口crates/bongocat-overlay/src/placement.rs其状态机行为包括检查缓存复用当窗口矩形未变且距上次检查不足PLACEMENT_INSPECTION_INTERVAL时复用上次的检查结果不重新枚举显示器测试a_settled_inspection_is_reused_and_revalidated验证 60fps 帧循环下 30 帧只查询了一次显示器。位移即重计时观察到窗口矩形变化或这是启用约束后的第一次观察就清空倒计时。这保证拖拽中的窗口永远不会被纠正也保证用户关闭设置期间摆放的位置不会在重新打开时被立刻移动。到期才纠正只有不符合并集覆盖的摆放持续静止满PLACEMENT_SETTLE_DELAY后才返回纠正矩形纠正结果与当前矩形相同如超大窗口已钉在显示器原点被视为无事可做不产生新的移动因此不会每帧重复SetWindowPos。取消挂起纠正倒计时期间重新评估发现窗口已重新合法如插入了新显示器会清掉倒计时此后若再次越界需要重新静止 1 秒而不是让旧的截止时间立刻触发测试a_display_plugged_in_during_the_countdown_cancels_the_correction覆盖此场景。五、平台适配只负责枚举显示器与读写窗口矩形两个平台的几何模块只实现 ADR 规定的枚举显示器 读写窗口矩形Windowscrates/bongocat-overlay/src/windows/geometry.rsscreen_bounds_all通过EnumDisplayMonitors枚举所有显示器回调collect_monitor中对每个显示器调用GetMonitorInfoW并取rcMonitor完整监视器矩形而非rcWork注释明确说明overlay 允许覆盖任务栏因此只有显示器本身是边界。枚举失败返回空列表而不是猜测值放置约束随即让窗口留在原地。overlay_bounds_visible用MonitorFromRect(.., MONITOR_DEFAULTTONULL)判断矩形是否可见。macOScrates/bongocat-overlay/src/macos/geometry.rsscreen_bounds_all遍历NSScreen::screens取每个屏幕的frame()完整 frame含菜单栏与 Dock 占用的条带并通过rounded_i32/rounded_u32把浮点坐标安全转为整数。几何模块头部注释还强调 AppKit 从主显示器左下角度量、CoreGraphics 从左上角度量的坐标翻转问题凡是跨这两个空间的坐标都要在此镜像。会话侧Windows 的 crates/bongocat-overlay/src/windows/session.rs持有OverlayPlacementConstraint实例与session_started: Instant单调时钟基座并在 frame tick 中调用observe喂入实时窗口矩形返回的纠正矩形由会话应用到原生窗口。另外在 crates/bongocat-overlay/src/bounds.rs 中OverlaySessionOptions::requires_window_recreation表明corner_radius_percent与keep_inside_screen两个字段的变更需要重建原生窗口资源而点击穿透、置顶、缩放、透明度等变更可直接作用于原生表面。六、测试验证没有 GPU 和原生窗口也能测ADR 强调判定与倒计时都可以在没有 GPU 和原生窗口的情况下测试placement.rs内置的#[cfg(test)]测试模块完整验证了这套逻辑crates/bongocat-overlay/src/placement.rs包括单显示器 / 跨屏 / 完全覆盖并集a_window_on_one_display_is_inside验证恰好覆盖两块显示器的窗口-1920,0,3840,1080仍合法。跨接缝合法a_window_straddling_two_displays_is_inside验证跨接缝窗口以及同时压在两块显示器底部任务栏条带上的窗口都合法——因为边界是显示器而非工作区。越界判定a_window_off_the_desktop_is_not_inside覆盖左右上下四方向越界与空显示器列表。L 形桌面凹槽a_window_in_the_notch_of_an_l_shaped_desktop_is_not_inside验证两个水平切片都触碰显示器但整体仍落在桌面外的窗口左高右矮、顶部对齐的布局下矮显示器下方是无桌面区域会被判定为不合法。重叠显示器overlapping_displays_cover_their_shared_regions验证显示器重叠区域的覆盖判定。纠正目标选择the_correction_targets_the_display_with_the_largest_overlap、a_window_touching_no_display_targets_the_nearest_one验证最大交叠优先、无交叠取最近、空列表返回None。延迟与重计时a_settled_window_off_the_desktop_is_corrected_only_after_the_delay截止时间排他、every_observed_movement_restarts_the_countdown拖拽期间位移持续重计时释放后满 1 秒才纠正、a_window_that_returns_to_the_desktop_is_never_corrected回到桌面的窗口永不纠正。启用约束后的首次观察the_first_observation_after_enabling_starts_a_fresh_countdown保证打开设置不会立刻搬动窗口。七、后果与已知边界ConsequencesADR 的 Consequences 章节明确记录了行为变化与未验证项这些同样需要在文章中如实呈现行为变化任务栏、Dock 和菜单栏所在区域不再是禁区窗口可以停留在其上窗口被拖出桌面后会有一段可见的停留随后才自动回到显示器内——这是延迟的有意结果也是跨显示器拖拽可用的前提。失去的能力不再保证窗口避开系统栏always_on_top开启时 overlay 可以覆盖 macOS 菜单栏。需要让开任务栏时改由用户自己摆放。超大窗口一个大于所有显示器的窗口永远无法完整显示约束只会把它贴到显示器原点且不再产生新的移动不会每帧重复SetWindowPos。隐藏窗口不动纠正发生在 frame tick 内overlay 不可见或 frame source 已停止时不会纠正隐藏的窗口保留原位置。热插拔自愈延迟显示器热插拔靠500ms定期重评估自愈没有监听WM_DISPLAYCHANGE/NSApplicationDidChangeScreenParametersNotification拓扑变化到窗口纠正之间最多有重评估间隔 静止延迟的延迟。ADR 明确建议若后续需要更快响应应加平台通知而不是缩短这两个常量。未验证项两平台真实鼠标拖拽观感、多显示器实机摆放与显示器热插拔均未实机核验ADR 记录当时开发环境只有 macOS 单显示器Windows 交叉工具链无法构建 overlay 的 C 依赖。八、相关演进与延伸阅读ADR-0045 的正文标注了后续修订ADR-0054 后项目不再维护 AccessKit 标签同步字段改名后的当前收口是中英文案、共享 schema、fixture 与可见控件。仓库中相关证据包括配置 schema 与默认值crates/bongocat-config/src/config_schema/overlay.rs 、shared/config/fixtures/default.json放置判定核心与常量crates/bongocat-overlay/src/placement.rs平台几何适配crates/bongocat-overlay/src/windows/geometry.rs、crates/bongocat-overlay/src/macos/geometry.rs会话集成与窗口重建判定crates/bongocat-overlay/src/windows/session.rs、crates/bongocat-overlay/src/bounds.rs相关 ADRdocs/adr/0045-overlay-placement-screen-bounds.md、docs/adr/0057-overlay-resize-by-right-button-drag.md总体而言ADR-0045 是一次典型的把平台专属逻辑收敛为可移植纯逻辑 平台薄适配层的架构收敛把显示器枚举和窗口读写留在平台层把并集覆盖判定、纠正目标选择与延迟倒计时全部下沉到无 GPU、无窗口依赖的纯 Rust 模块中并用一组边界完备的单元测试钉死语义。对想要理解或修改 BongoCat overlay 放置行为的开发者来说placement.rs是唯一需要重点阅读的文件。赞分享桌面应用【免费下载链接】BongoCat BongoCat — A cross-platform interactive desktop pet that brings fun to your desktop!项目地址https://gitcode.com/gh_mirrors/bong/BongoCat点击查看免费下载相关推荐tsParticles Fireworks 预设全解读从 v1.18 到 v4.3.3 的版本演进与配置源码剖析tsParticles Fireworks 预设全解读从 v1.18 到 v4.3.3 的版本演进与配置源码剖析 tsParticles 的 tsparti前端Mi-Create多语言系统实战基于gettext的7语言桌面应用国际化完整指南Mi Create多语言系统实战基于gettext的7语言桌面应用国际化完整指南 Mi Create 是一款面向小米可穿戴设备的开源表盘制作工具支持 202桌面应用Puma系统资源限制ulimit配置与进程约束Puma系统资源限制ulimit配置与进程约束 你是否曾遇到过Puma服务器在高并发场景下突然崩溃日志中出现too many open files错误后端网络上一篇如何高效编辑《英雄联盟》Wad文件Obsidian2编辑器的完整指南 下一篇如何释放GPU显存ComfyUI-MultiGPU终极指南让AI绘图突破设备限制创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表