资讯详情

Tinycast WindowActionMemory 详解:单级还原点与窗口布局写入隔离如何实现

📅 2026/9/20 23:57:39 | 华诺云谱 👁 阅读
Tinycast WindowActionMemory 详解:单级还原点与窗口布局写入隔离如何实现
Tinycast WindowActionMemory 详解单级还原点与窗口布局写入隔离如何实现【免费下载链接】tinycastTinycast — a tiny, fully native macOS launcher, hotkeys, and clipboard history.项目地址: https://gitcode.com/GitHub_Trending/ti/tinycastTinycast 是一款完全原生的 macOS 启动器内置窗口管理、全局快捷键与剪贴板历史功能。本文讲解其窗口管理核心组件WindowActionMemory窗口动作记忆的两个关键设计如何用单级还原点实现一键 Restore 回到原位以及为什么窗口布局Window Layouts的批量写入必须与它完全隔离。为什么窗口管理需要记忆Tinycast 提供 35 个窗口命令左右半屏、四分之一屏、最大化、跨显示器移动等可通过调色板或全局快捷键触发官方说明见 docs/features/window-management.md。要实现按一次 Restore 就能回到 Tinycast 动你之前的体验程序必须回答一个问题这个窗口在 Tinycast 第一次碰它之前长什么样答案就存在WindowActionMemory里源码位于 WindowActionMemory.swift。它为每个窗口保存一条Record字段含义restoreFrameTinycast 第一次触碰前的原始位置还原点appliedFrame上次写入后实际观察到的落点而不是我们要求的值command上一次使用的命令 ID自定义尺寸时为nilstep当前循环步进位置半屏→三分之一→三分之二screenID/originScreenID窗口所在屏 / 循环链起始屏at时间戳用于循环超时判定整个结构是纯 Foundation CoreGraphics 实现不依赖 AX、不读时钟时间由调用方传入now因此可以无头测试。decide 的 4 条判定规则循环步进怎么算每次按下快捷键WindowMover 会先调用decide拿决策再执行写入。规则按顺序执行见 decide 源码首次见到该窗口→ 步进归零把当前帧捕获为还原点此时canRestore false没有可回退的地方。当前帧与appliedFrame偏差超过 2pt 容差→ 判定用户自己动过窗口循环重启并刷新还原点。换了命令、换了显示器、循环长度为 1 或超时→ 循环重启从第 0 步开始。其余情况→(step 1) % cycleLength循环继续推进。两个细节格外重要规则 2 对比的是观察到的帧永远不是要求的帧。终端应用按字符格缩放落点永远不会精确等于目标若与目标对比每次按键都会被误判为用户拖动循环和 Restore 双双失效。还原点是单级的不是栈。左半屏 → 最大化 → 右上角 → Restore最终落回最初的位置因为还原点只在首次捕获、中间动作绝不覆盖它。官方文档的解释很直白window-management.md · Cycling and Restore 指出栈式还原对第二次按 Restore 应该回到哪没有可辩护的答案。commit只记录真正落地的结果decide是纯查询真正写入发生在commit见 commit 源码WindowMover通过 AX 完成尺寸 → 位置 → 尺寸的写入序列后回读一次真实帧才提交给记忆。这一读有三重用途探测应用强加的最小尺寸AX 无对应属性回读是唯一手段、记录如实的appliedFrame、判断这次操作是否真的改变了什么。布局写入隔离WindowLayoutRunner 绝不触碰记忆Window Layouts 是保存好的多窗口摆位一条命令把整个桌面按图纸摆正。它的执行器 WindowLayoutRunner 虽然复用同一套 AX 写入能力但有一条铁律文档不变量Runner 从不触碰WindowActionMemory。原因有两个都源于单级还原点的设计还原点会被覆盖。布局一次性重排十几个窗口若每次都commit原始还原点会被布局写入的值顶掉Restore 就回不去了。循环链会被误杀。布局移动了窗口下次按左半屏时规则 2 会认为用户自己动过它而重启循环——这在语义上是错的动窗口的是 Tinycast 自己。隔离的可见后果布局运行后按 Restore回到的是最后一次窗口命令之前的位置而不是布局运行之前的位置。这是有意为之的取舍。另一个相关机制是全屏命令WindowMover切换全屏后调用 forgetCycle打断循环链但保留还原点——macOS 自己会恢复全屏前的帧但用户最初的位置仍然是正确的 Restore 目标。记忆不膨胀LRU、退出清理与超时长会话里窗口来来去去记忆通过三种方式保持有界LRU 上限 64内部维护最久未使用顺序超限直接淘汰最旧条目应用退出监听监听NSWorkspace.didTerminateApplicationNotification进程一退就按 pid 批量清除其全部窗口记录不等 LRU 慢慢回收见 WindowMover 初始化cycleTimeout可选超时后冷启动的按键不会继续半截循环而是重新从头开始。此外什么都不持久化——重启即清空这是刻意的跨重启的旧还原点往往已经失真。测试如何锁定这些行为上述每条规则都由 Tests/window-command-test.swift 以Int为键的纯内存实例驱动验证包括循环推进不扰动还原点、换命令/换屏重启循环、跨屏链保持起始屏计数用户拖动重启循环并重新锚定还原点而 1pt 以内的量化落差不触发误判连续多条不同命令后 Restore 仍回到真实原位且第二次 Restore 幂等LRU 淘汰精确保留最近 64 条、forget(where:)按条件批量清理。整个模块 500 条断言全部无头运行因为WindowActionMemory与几何引擎一样保持了纯粹的 Foundation CoreGraphics 分层见 架构文档。小结WindowActionMemory的设计哲学可以用三句话概括decide 只做纯查询、commit 只信回读值、还原点单级且不可被中间动作覆盖。而 Window Layouts 对它的彻底隔离则保证了两种移动窗口的语义互不污染——这正是窗口管理器在真实桌面上既可靠又可预期的基础。记忆模型WindowActionMemory.swift写入策略WindowMover.swift布局执行器WindowLayoutRunner.swift功能文档window-management.md · window-layouts.md【免费下载链接】tinycastTinycast — a tiny, fully native macOS launcher, hotkeys, and clipboard history.项目地址: https://gitcode.com/GitHub_Trending/ti/tinycast创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。