Milestone 5: 窗口管理可见¶
状态: ⬜ 待开始 预计周期: 7-10 天 前置依赖: Milestone 3: 任务栏 (任务栏联动) 目标: 外部应用窗口能被管理——有窗口装饰,支持最小化/最大化/关闭,任务栏同步显示运行中应用
一、阶段目标¶
扩展 WindowManager 使其支持窗口状态管理,实现窗口装饰 Widget (标题栏 + 控制按钮),并与 Taskbar 联动显示运行中应用。
完成标志: 启动外部应用后,任务栏出现对应图标,点击图标可 raise/minimize 窗口,窗口有自定义标题栏装饰。
二、当前状态分析¶
已有基础设施¶
| 组件 | 文件 | 状态 |
|---|---|---|
WindowManager |
desktop/ui/components/WindowManager.h/.cpp |
✅ 基础:create_window() / find_window() / request_close_window() / raise_a_window() |
IWindow |
desktop/ui/components/IWindow.h |
✅ title() / geometry() / close() / raise() / set_geometry() |
IWindowBackend |
desktop/ui/components/IWindowBackend.h |
✅ window_came / window_gone 信号 |
WSL X11 Backend |
desktop/ui/platform/linux_wsl/ |
✅ XCB 窗口追踪 |
Windows Backend |
desktop/ui/platform/windows/ |
✅ Win32 窗口追踪 |
| Material Button | ui/widget/material/widget/button/ |
✅ 窗口控制按钮 |
| CenteredTaskbar | MS3 中实现 | ✅ updateRunningState() |
关键缺口¶
- 没有 WindowInfo 数据结构 — 只有 IWindow 的基础属性
- 没有 WindowState 状态机 — 窗口没有 Normal/Minimized/Maximized 概念
- 没有窗口装饰 — 没有自定义标题栏
- 没有布局策略 — 窗口没有布局管理
- Taskbar 未与 WindowManager 联动 — 运行状态未同步
三、待实现任务¶
Day 1-2: 窗口数据模型¶
Step 1: 定义 WindowInfo¶
- [ ] 创建文件
desktop/ui/components/window_manager/window_info.henum class WindowState { Normal, Minimized, Maximized, Fullscreen, Closing, Closed }; struct WindowInfo { QString window_id; QString title; QString icon_hint; // 图标提示 (PID → 图标查找) qint64 pid{0}; QRect geometry; WindowState state{WindowState::Normal}; int z_index{0}; bool is_always_on_top{false}; QDateTime created_at; }; - [ ] 实现窗口状态转换规则:
Step 2: 扩展 WindowManager¶
- [ ] 修改
desktop/ui/components/WindowManager.h: - 添加
QHash<win_id_t, WindowInfo> window_infos_存储窗口信息 - 添加方法:
- 添加信号:
- [ ] 在
window_came回调中创建 WindowInfo 并填充 - [ ] 在
window_gone回调中将状态设为 Closed
Day 3-4: 窗口装饰 Widget¶
Step 3: 创建 WindowDecoration 类¶
- [ ] 创建文件
desktop/ui/components/window_manager/window_decoration.h/.cpp - [ ] 这是一个可视化装饰层,显示在窗口上方 (overlay 模式)
class WindowDecoration : public QWidget { Q_OBJECT public: explicit WindowDecoration(QWidget* parent = nullptr); void setTitle(const QString& title); void setIcon(const QPixmap& icon); signals: void closeClicked(); void minimizeClicked(); void maximizeClicked(); protected: void paintEvent(QPaintEvent*) override; void mousePressEvent(QMouseEvent*) override; void mouseMoveEvent(QMouseEvent*) override; // 拖拽标题栏 private: void setupButtons(); void applyTheme(); }; - [ ] 布局:
- [ ] 标题栏内容:
- 左侧: 应用图标 + 窗口标题
- 右侧: 最小化(─)、最大化(□)、关闭(✕) 按钮
- [ ]
paintEvent(): - 绘制标题栏背景 (
theme->colorScheme().surface()) - 绘制标题文字 (
theme->colorScheme().onSurface()) - 绘制窗口边框/阴影
- [ ] 窗口控制按钮:
- 使用 Material IconButton (文本变体) 或自定义绘制
- 关闭按钮 hover: 红色背景 (
theme->colorScheme().error()) - 其他按钮 hover:
theme->colorScheme().surfaceVariant()
Step 4: 标题栏拖拽移动¶
- [ ]
mousePressEvent: 记录起始位置 - [ ]
mouseMoveEvent: 计算偏移 → 调用IWindow::set_geometry() - [ ] 双击标题栏 → 切换最大化/恢复
注意: 窗口装饰的位置取决于平台后端。在 WSL X11 客户端模式下,外部窗口由 XWayland/Weston 管理,CFDesktop 只能追踪而无法直接装饰。窗口装饰需要以下策略之一: - 策略 A (推荐初期): 在 CFDesktop 自己的 overlay 上渲染装饰信息,作为纯视觉指示 - 策略 B (后期): 实现 X11 窗口管理器功能,实际管理外部窗口 - 策略 C (后期): 在 Wayland Compositor 模式下完全控制窗口装饰
Day 5-6: Taskbar 联动¶
Step 5: Taskbar ↔ WindowManager 联动¶
- [ ] 在 CFDesktopEntity 中连接:
- [ ]
onWindowInfoUpdated(): - 新窗口出现 → taskbar 添加图标 (匹配 AppEntry)
- 窗口关闭 → taskbar 移除图标
- 窗口状态变化 → 更新指示器
- [ ]
onTaskbarAppClicked(): - 窗口已激活 → minimize
- 窗口已最小化 → restore + raise
- 未运行 → 启动应用
Step 6: 运行中应用列表同步¶
- [ ] WindowManager 维护
QList<WindowInfo>活跃窗口列表 - [ ] 信号
windowListChanged()→ Taskbar 刷新图标
Day 7-8: 布局策略 (基础版)¶
Step 7: 实现 FloatingPolicy (最简版)¶
- [ ] 创建文件
desktop/ui/components/window_manager/floating_policy.h/.cpp - [ ] 功能:
- 新窗口出现在屏幕中心
- 窗口可拖拽 (通过 WindowDecoration)
- 窗口可缩放 (8 个方向的 resize handle,可延后)
- 最小尺寸限制 (320x240)
- [ ] 计算新窗口初始位置:
Day 9-10: 集成与验证¶
Step 8: 全流程集成¶
- [ ] 启动应用 → AppLauncher → QProcess
- [ ] 外部窗口出现 → IWindowBackend::window_came → WindowManager 注册
- [ ] WindowManager 更新 WindowInfo → 通知 Taskbar
- [ ] Taskbar 显示运行中图标
- [ ] 点击 Taskbar 图标 → raise/minimize 窗口
Step 9: 验证场景¶
- [ ] 启动 xterm → 任务栏出现终端图标
- [ ] 点击任务栏图标 → 终端窗口被 raise
- [ ] 再次点击 → 终端窗口被 minimize
- [ ] 关闭终端 → 任务栏图标消失
四、关键文件清单¶
需要新建的文件¶
| 文件 | 内容 |
|---|---|
desktop/ui/components/window_manager/window_info.h |
窗口数据模型 |
desktop/ui/components/window_manager/window_decoration.h |
窗口装饰声明 |
desktop/ui/components/window_manager/window_decoration.cpp |
窗口装饰实现 |
desktop/ui/components/window_manager/floating_policy.h |
浮动布局策略 |
desktop/ui/components/window_manager/floating_policy.cpp |
浮动策略实现 |
需要修改的文件¶
| 文件 | 修改内容 |
|---|---|
desktop/ui/components/WindowManager.h |
添加 WindowInfo 存储、状态管理方法、新信号 |
desktop/ui/components/WindowManager.cpp |
实现扩展方法 |
desktop/ui/CFDesktopEntity.cpp |
连接 WM ↔ Taskbar 信号 |
desktop/ui/components/taskbar/centered_taskbar.h |
添加 onWindowInfoUpdated() 方法 |
desktop/ui/components/CMakeLists.txt |
添加新文件 |
参考文件 (只读)¶
| 文件 | 用途 |
|---|---|
desktop/ui/components/WindowManager.h:39 |
现有 WM 类 |
desktop/ui/components/IWindow.h |
IWindow 接口 |
desktop/ui/components/IWindowBackend.h |
窗口后端信号 |
desktop/ui/platform/linux_wsl/wsl_x11_window_backend.cpp |
X11 窗口追踪 |
desktop/ui/platform/windows/windows_window_backend.cpp |
Windows 窗口追踪 |
document/todo/desktop/09_window_manager.md |
原始窗口管理设计 |
五、验收标准¶
- [ ] 启动外部应用后 WindowManager 能追踪到新窗口
- [ ] WindowManager 维护 WindowInfo 数据 (标题、PID、状态)
- [ ] 窗口状态可在 Normal/Minimized/Maximized 之间转换
- [ ] Taskbar 同步显示运行中应用图标
- [ ] 点击 Taskbar 图标可 raise/minimize 对应窗口
- [ ] 窗口有自定义装饰 (至少标题 + 关闭按钮的视觉呈现)
- [ ] 窗口关闭后 Taskbar 图标自动消失
- [ ] Light/Dark 主题切换时装饰正确变色
最后更新: 2026-03-31