base: Add window_ext for overlay/floating window configuration - #2964
base: Add window_ext for overlay/floating window configuration#2964panzhifu wants to merge 9 commits into
Conversation
Provides cross-platform APIs to configure OS-level window behavior: - Skip taskbar (hide from taskbar/dock/alt-tab) - Click-through (mouse events pass through window) - Always on top (window stays above other windows) Supports macOS (NSWindow), Windows (Win32 API), and Linux/X11. Wayland is not supported due to protocol limitations. Generated with assistance from Claude Code.
Fix Windows build errors: - WINDOW_EX_STYLE is u32, not a struct - SetWindowLongW/SetWindowPos take specific types - SWP_* flags are SET_WINDOW_POS_FLAGS type Generated with assistance from Claude Code.
- Use NSView::window() to get NSWindow from AppKitWindowHandle - Replace NSUInteger with usize for collection behavior - Remove unused ClassType import Generated with assistance from Claude Code.
- Cast ns_view through as_ptr() instead of direct NonNull cast - Use &*ns_window reference for msg_send! (Retained is not MessageReceiver) Generated with assistance from Claude Code.
…import - Use windows_sys (not windows) crate for Windows API - Remove unused NSWindow import on macOS Generated with assistance from Claude Code.
- HWND is a type alias, use type annotation instead of construction - WS_EX_* are u32 constants, not newtypes (no .0 field) Generated with assistance from Claude Code.
- windows-sys HWND is *mut c_void, use is_null() not is_invalid() - handle.hwnd is NonZero<isize>, use .get() to extract raw value Generated with assistance from Claude Code.
There was a problem hiding this comment.
目前不建议合并,需要先澄清功能意图与架构归属,再处理实现问题。
PR 描述只列出了 skip taskbar、click-through 和 always-on-top 三个开关,没有说明具体应用场景、现有 WindowOptions / WindowKind::{Floating, PopUp} 为什么不能满足需求,以及为什么需要在 gpui-base 增加这组公开 API。描述中仍保留了未填写的模板内容,也没有可复现的功能测试步骤。请先补充这些信息。
此类新增功能必须随代码提交可运行的示例,明确展示实际使用场景;这是本次修改的合并要求,不是可选补充。 请在仓库中提供独立 example 或合适的 Story,说明用户要完成什么任务、为什么需要这些窗口行为,并展示窗口创建、配置调用、开关切换及预期效果。在 PR 中给出启动命令、操作步骤、适用平台和验证结果。仅提交 API 实现、零散文档片段,或笼统勾选“已运行 Story”,不能替代这个示例。示例也应让维护者能够实际复现并评估需求是否应该由本项目承担。
这些能力直接涉及原生窗口层级、输入区域和窗口管理器协议,原则上应由 GPUI 的平台窗口层统一维护。在 gpui-base 直接操作原生句柄,会绕过 GPUI 对窗口状态的管理,并让基础组件层承担另一套平台实现。请优先在 GPUI 层讨论和实现;如果确实需要在这里提供适配,请说明边界、现有 API 的缺口,以及如何与 GPUI 的状态保持一致。
当前代码还存在以下具体问题(基于 f58f9a06cd7ee1183e56bfb6735bbaea414ccd58,行号均指 crates/base/src/window_ext.rs):
-
X11 分支不会执行(第 111 行):这里只匹配
RawWindowHandle::Xlib,但当前锁定版本 GPUI 的 X11 后端返回XcbWindowHandle。实际调用会落入_ => {},三个配置都静默无效。 -
macOS 常量错误(第 175–183 行):
1 << 6实际是IgnoresCycle,1 << 7和1 << 8分别是FullScreenPrimary、FullScreenAuxiliary,并非注释所述含义;后两个还是不能同时指定的选项。ExcludedFromWindowsMenu是独立 setter。请使用 AppKit 的类型化常量和方法,避免手写位值。 -
macOS 无法恢复配置(第 172–203 行):只在选项为
true时设置系统状态,传入false不执行恢复。例如先set_click_through(window, true)再传false,窗口仍不接收鼠标事件。置顶和 collection behavior 也有类似问题。 -
Windows 覆盖了已有扩展样式(第 230–247 行):从零构造
ex_style,再通过SetWindowLongW整体替换,会清掉 GPUI 设置的WS_EX_NOREDIRECTIONBITMAP、对话框样式等。应保留无关标志,仅修改该功能负责的位。参见 SetWindowLongW 文档。 -
切换穿透会重置 Windows 浮窗行为(第 142–143 行):
set_click_through()用其余字段均为false的完整配置调用configure()。因此make_floating()后调用它,会取消置顶及隐藏任务栏配置,而不是只改变鼠标穿透。 -
X11 点击穿透没有实现(第 326–333 行):即使修正句柄匹配,设置
_NET_WM_WINDOW_TYPE_SPLASH也只是改变窗口类型,没有修改输入区域,不能实现鼠标事件穿透。需要实际处理 input shape,并支持恢复。参见 X Shape 协议。 -
X11 状态更新方式不正确且相互覆盖(第 294–323 行):对已映射窗口,应向根窗口发送
_NET_WM_STATEClientMessage,而不是直接替换属性。当前PropModeReplace每次只写一个 atom,写入ABOVE还会覆盖之前的SKIP_TASKBAR及已有状态。参见 EWMH 规范。 -
新增文档测试失败(第 12、30、92 行):
gpui-base的 doctest 无法解析未依赖的gpui_kit;示例还包含不存在的.skip_taskbar()/.click_through()/.always_on_top()方法,以及未定义的window。no_run仍然需要编译通过。
本地执行 cargo test -p gpui-base --doc --locked --offline,结果为 14 passed、3 failed、7 ignored,失败的三项均来自本次新增模块。平台行为问题依据当前锁定依赖源码和协议核对,未在 macOS / Windows 上运行复现。
请先明确需求与实现层级,再提供各支持平台的可复现验证,至少覆盖开启/关闭、选项组合、保留已有窗口状态,以及不支持平台的明确行为。当前 CI 通过不足以证明这些原生窗口功能正确。
Panels that don't need zoom/close affordances (e.g. a fixed sidebar) currently have no way to remove the ⋯ button. This adds DockSkin::ellipsis_menu(true) so callers can hide it. Default is unchanged. Refs longbridge#2983
- configure() and platform functions now return Result<()> instead of silently ignoring failures - Windows: check SetWindowLongW/SetWindowPos return values, report OS errors - macOS: document window level constant (5 = above floating) - Linux: document click-through as partial (XShape not implemented), document per-call Display connection - Add builder roundtrip and default-value tests
Provides cross-platform APIs to configure OS-level window behavior:
Supports macOS (NSWindow), Windows (Win32 API), and Linux/X11. Wayland is not supported due to protocol limitations.
Generated with assistance from Claude Code.
Closes #[issue number]
Description
Describe in English for the changes made in this pull request and the problem it solves.
Please keep 1 PR to solve 1 problem, and keep Small improvements should be small modifications to make PR easier to review and to merge.
Screenshot
Break Changes
Describe any breaking changes introduced by this pull request. If none, remove this section.
How to Test
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce.
Checklist
cargo runfor story tests related to the changes.