mcpField
W
window-management

window-management

github.com/openai设计与 UI7.6k60 次安装3 周前更新
代码仓库

关于 window-management

面向开发者的技能,用于在 macOS 15 及更高版本中按用途定制 SwiftUI 窗口。它指导场景选择、窗口外观、行为与位置设置,并建议仅在 SwiftUI 修饰符无法满足需求时桥接 AppKit。

主要功能

  1. 01按窗口用途选择场景
  2. 02自定义工具栏与标题
  3. 03配置拖动区域和材质
  4. 04设置恢复与启动行为
  5. 05控制初始位置和缩放布局
  6. 06检查窗口可用性

适用场景

  1. 01设计实用工具或关于窗口
  2. 02定制媒体播放器窗口
  3. 03选择窗口恢复行为
  4. 04按显示器尺寸设置窗口大小

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/openai/plugins --skill window-management

安装后在 Claude Code 中输入/window-management确认已加载。

附带文件agents/openai.yamlreferences/api-snippets.md

详细介绍

窗口管理

概览

使用此技能,让每个 SwiftUI 窗口都适合其用途。首先确定哪个场景拥有该窗口(Window、WindowGroup 或专用工具场景),然后自定义工具栏/标题区域、背景材质、调整大小与恢复行为,以及初始位置或缩放后的位置。

如果 SwiftUI 能直接提供所需行为,优先使用场景和窗口修饰符,而不是临时搭建 AppKit 桥接。让每个窗口各司其职:主浏览窗口、“关于”窗口和媒体播放器窗口通常需要不同的窗口装饰、可调整大小设置、恢复规则和位置规则。

这些是 macOS 15+ 的 SwiftUI 窗口/场景自定义 API。对于较早的部署目标,预计需要使用更多 AppKit 桥接或可用性检查。

工作流

  1. 检查相关的场景声明,并确定窗口用途:主应用导航、检查器/详情工具窗口、“关于”/支持窗口、媒体播放窗口、欢迎窗口或无边框自定义界面。
  2. 调整工具栏和标题的显示方式,使其与内容相符。
  3. 如果隐藏了工具栏背景或整个工具栏,请确保窗口仍有可用的拖动区域。
  4. 根据窗口用途调整行为:最小化是否可用、恢复规则、调整大小的预期,以及窗口是否应在启动时出现。
  5. 为新打开的窗口设置默认位置,并在内容和显示器尺寸很重要时,为缩放行为设置理想位置。
  6. 使用 build-run-debug 构建并启动应用,在真实的前台 .app 捆绑包中验证结果。
  7. 如果 SwiftUI 场景/窗口修饰符无法满足需求,请改用 appkit-interop,通过精简的 NSWindow 桥接实现,而不是让 AppKit 代码遍布整个视图树。

工具栏与标题

  • 当窗口标题应继续与窗口关联,以便用于辅助功能和菜单,但不应在标题栏中可见时,使用 .toolbar(removing: .title)。
  • 当大型媒体内容或主视觉内容需要在视觉上延伸至窗口顶部边缘时,使用 .toolbarBackgroundVisibility(.hidden, for: .windowToolbar)。
  • 如果窗口仍需关闭/最小化/全屏控制按钮,只移除标题和工具栏背景。如果要彻底隐藏工具栏,则改用 .toolbarVisibility(.hidden, for: .windowToolbar)。
  • 在叠加新的 SwiftUI 工具栏 API 之前,移除自定义工具栏背景和手绘的标题栏填充。
  • 即使标题隐藏,也应让窗口的逻辑标题具有明确含义;系统仍可将其用于辅助功能和菜单项。这些变化仅影响视觉呈现。

拖动区域

  • 如果隐藏了工具栏背景或彻底移除了工具栏,请使用 WindowDragGesture() 将可拖动区域延伸到内容区域。
  • 将手势附加到透明叠加层或非交互式标题区域,避免拦截实际控件的手势。
  • 对于带有自定义播放控制的媒体播放器,请将拖动叠加层置于视频内容和控制项之间,以便 AVKit 或传输控制项继续接收输入。
  • 将拖动手势与 .allowsWindowActivationEvents(true) 配合使用,以便点击并立即拖动后台窗口时,窗口仍会激活并移动。

背景与材质

  • 当工具窗口或“关于”窗口应以微妙的磨砂材质替代默认窗口背景时,使用 .containerBackground(.thickMaterial, for: .window)。
  • 为风格化窗口优先使用系统材质,而不是硬编码半透明颜色。
  • 对于固定内容的工具窗口,如果柔和的背景是设计的一部分,更应使用这种方式。

窗口行为

  • 对于始终易于访问的实用工具窗口(例如自定义“关于”窗口),使用 .windowMinimizeBehavior(.disabled),因为最小化几乎没有价值。
  • 当窗口内容只有一种预期尺寸时,通过固定尺寸或窗口约束禁用绿色缩放控件。
  • 对于不应在下次启动时重新打开的窗口(例如“关于”面板、临时支持/信息窗口或首次运行欢迎界面),使用 .restorationBehavior(.disabled)。
  • 对于主要文档窗口或导航窗口,如果重新打开时恢复之前的尺寸和位置更理想,则应启用状态恢复。
  • 默认情况下,SwiftUI 会遵循用户在 macOS 系统范围内设置的状态恢复选项。只有当特定窗口需要有意选择遵循或不遵循此系统行为时,才使用 restorationBehavior(...)。
  • 对于应在启动时首先显示的窗口(例如欢迎窗口),使用 .defaultLaunchBehavior(.presented),并有意选择此行为,而不要依赖场景创建顺序产生的副作用。

窗口放置

  • 使用 .defaultWindowPlacement { content, context in ... } 控制新打开窗口的初始尺寸和可选位置。
  • 在放置闭包中,调用 content.sizeThatFits(.unspecified) 获取内容的理想尺寸。
  • 读取 context.defaultDisplay.visibleRect,获取扣除菜单栏和 Dock 后显示器的可用区域。
  • 如果媒体或文档内容可能大于显示器,则返回尺寸限制在可见区域内的 WindowPlacement(size: size)。如果未提供位置,窗口默认居中。
  • 使用 .windowIdealPlacement { content, context in ... } 控制用户从“窗口”菜单选择“缩放”或按住 Option 键并点按绿色工具栏按钮时的行为。对于媒体窗口,应保持宽高比,并扩展到显示器所能容纳的最大尺寸。
  • 将默认放置和理想放置视为两种独立策略:
    • 默认放置控制新窗口首次出现的位置;
    • 理想放置控制缩放后的窗口应达到多大。
  • 根据内容尺寸调整播放器窗口或文档窗口时,始终考虑外接显示器以及旋转或较窄的屏幕。

无边框和专用窗口

  • 对于无边框或高度自定义窗口装饰的窗口,使用 .windowStyle(.plain),但应确保内容提供清晰的拖动操作区域和可见上下文。
  • 对于无边框播放器、HUD 或欢迎窗口,应事先决定,失去标准标题栏操作是否值得换取自定义呈现方式。
  • 如果普通样式让窗口变得不明显或难以移动,应保留一条清晰的路径,以便恢复常规窗口管理方式。

如需查看具体的窗口修饰符示例,请阅读 references/api-snippets.md。

审查清单

  • 场景类型与窗口的用途和生命周期相匹配。
  • 隐藏标题后,仍保留有意义的逻辑标题,以供辅助功能和菜单使用。
  • 移除工具栏背景是有意为之,且不会影响标题栏的易读性或窗口控件的位置。
  • 隐藏或移除工具栏的窗口仍具有可靠的拖动区域,并支持从背景处点按后拖动来激活窗口。
  • 实用工具窗口的恢复和最小化行为符合其用途。
  • 仅当场景需要有意区别于用户的系统范围设置时,才覆盖恢复行为。
  • 当内容尺寸和显示器尺寸会产生影响时,默认放置和理想放置会使用 content.sizeThatFits(.unspecified) 和 context.defaultDisplay.visibleRect。
  • 媒体窗口保持宽高比,并能适应较小或旋转的显示器。
  • 无边框窗口仍提供可用的移动/拖动操作区域。

注意事项

  • 不要只为隐藏忘记设置的标题而使用 .toolbar(removing: .title)。 应确保底层窗口标题有意义。
  • 不要隐藏工具栏背景或整个工具栏,除非同时提供替代的拖动操作方式。
  • 除非用户明确希望应用每次启动时都从头开始,否则不要对主文档/导航窗口禁用恢复功能。
  • 调整播放器窗口大小时,不要将某一种显示器尺寸写死,也不要假设只有一个显示器。
  • 在尝试修改 NSWindow 之前,先检查 .windowMinimizeBehavior、.restorationBehavior、.defaultWindowPlacement、.windowIdealPlacement、.windowStyle 或 .defaultLaunchBehavior 是否已能解决问题。
  • 不要留下没有明显拖动或关闭方式的纯无边框窗口。

何时使用其他技能

  • 对于更广泛的场景、命令、设置、侧边栏和检查器架构,请使用 swiftui-patterns。
  • 如果主要问题涉及现代 macOS 视觉设计、Liquid Glass 或采用系统材质,请使用 liquid-glass。
  • 如果自定义窗口行为确实需要 NSWindow、NSPanel 或响应者链控制,请使用 appkit-interop。
  • 要启动并验证生成的窗口,请使用 build-run-debug。

评论

支持 Markdown