|
| 1 | +# Milestone 1: 桌面骨架可见 |
| 2 | + |
| 3 | +> **状态**: ⬜ 待开始 |
| 4 | +> **预计周期**: 1-2 天 |
| 5 | +> **前置依赖**: 无 (当前基础设施已就绪) |
| 6 | +> **目标**: 运行后不再是空白,能看到一个带背景的全屏桌面窗口 |
| 7 | +
|
| 8 | +--- |
| 9 | + |
| 10 | +## 一、阶段目标 |
| 11 | + |
| 12 | +启动 CFDesktop 后,ShellLayer 渲染出桌面背景(纯色或壁纸),PanelManager 的可用区域计算正确,桌面主 Widget 正确显示。 |
| 13 | + |
| 14 | +**完成标志**: `./scripts/run.sh` 启动后看到全屏非空白的桌面画面。 |
| 15 | + |
| 16 | +--- |
| 17 | + |
| 18 | +## 二、当前状态分析 |
| 19 | + |
| 20 | +### 已有基础设施 |
| 21 | + |
| 22 | +| 组件 | 文件 | 状态 | |
| 23 | +|------|------|------| |
| 24 | +| `CFDesktop` (主 QWidget) | `desktop/ui/CFDesktop.h` | ✅ 已创建,`register_desktop_resources()` 可注入 PanelManager 和 ShellLayer | |
| 25 | +| `CFDesktopEntity` (生命周期) | `desktop/ui/CFDesktopEntity.h/.cpp` | ✅ 单例,`run_init()` 已接入 DisplayBackend | |
| 26 | +| `ShellLayer` | `desktop/ui/components/ShellLayer.h` | ✅ 接口+声明完整,**缺 .cpp 实现文件** | |
| 27 | +| `IShellLayer` | `desktop/ui/components/IShellLayer.h` | ✅ `setStrategy()` + `geometry()` 接口 | |
| 28 | +| `IShellLayerStrategy` | `desktop/ui/components/IShellLayerStrategy.h` | ✅ `activate(layer, wm)` + `deactivate()` + `onGeometryChanged()` | |
| 29 | +| `PanelManager` | `desktop/ui/components/PanelManager.h/.cpp` | ✅ 完整实现,`registerPanel()` / `availableGeometry()` | |
| 30 | +| `IPanel` | `desktop/ui/components/IPanel.h` | ✅ `position()` / `priority()` / `preferredSize()` / `widget()` | |
| 31 | +| `SimpleBootWidget` | `desktop/ui/widget/init_session/simple_boot_widget.h/.cpp` | ✅ 启动画面已完整 | |
| 32 | + |
| 33 | +### 关键缺口 |
| 34 | + |
| 35 | +1. **ShellLayer.cpp 不存在** — 只有 `.h` 声明,没有实现 |
| 36 | +2. **CFDesktop 没有 paintEvent** — 桌面主窗口不会画任何东西 |
| 37 | +3. **没有壁纸/背景渲染逻辑** — IShellLayerStrategy 没有具体实现 |
| 38 | +4. **CFDesktopEntity::run_init() 没有创建 ShellLayer** — 只做了 DisplayBackend 初始化 |
| 39 | +5. **CFDesktop 没有被 show()** — 桌面主 Widget 可能从未显示 |
| 40 | + |
| 41 | +--- |
| 42 | + |
| 43 | +## 三、待实现任务 |
| 44 | + |
| 45 | +### Day 1: ShellLayer 实现与桌面背景渲染 |
| 46 | + |
| 47 | +#### Step 1: 创建 ShellLayer.cpp |
| 48 | +- [ ] 创建文件 `desktop/ui/components/ShellLayer.cpp` |
| 49 | +- [ ] 实现构造函数 `ShellLayer(QWidget* parent)` |
| 50 | + - 设置 `setAttribute(Qt::WA_OpaquePaintEvent)` 减少闪烁 |
| 51 | + - 设置 `setAutoFillBackground(false)` |
| 52 | + - 接受 parent 的全尺寸 geometry |
| 53 | +- [ ] 实现 `setStrategy(std::unique_ptr<IShellLayerStrategy> strategy)` |
| 54 | + - 若已有旧 strategy,先调用 `deactivate()` |
| 55 | + - 存储新 strategy |
| 56 | + - 调用 `activate(this->GetWeak(), wm_weak)` 激活 |
| 57 | +- [ ] 实现 `geometry()` — 返回 `QWidget::geometry()` |
| 58 | +- [ ] 实现 `onAvailableGeometryChanged(const QRect& rect)` |
| 59 | + - 调用 `setGeometry(rect)` 调整 ShellLayer 尺寸 |
| 60 | + - 转发给 `strategy_->onGeometryChanged(rect)` |
| 61 | + |
| 62 | +**参考已有接口**: |
| 63 | +- `ShellLayer.h:35` — 类声明 |
| 64 | +- `IShellLayer.h:37` — 接口定义 |
| 65 | +- `IShellLayerStrategy.h:33` — 策略接口 |
| 66 | + |
| 67 | +#### Step 2: 创建 DefaultShellStrategy (桌面背景策略) |
| 68 | +- [ ] 创建文件 `desktop/ui/strategy/default_shell_strategy.h/.cpp` |
| 69 | +- [ ] 实现 `IShellLayerStrategy` 接口 |
| 70 | +- [ ] `activate()` 中: |
| 71 | + - 持有 ShellLayer 的 weak 引用 |
| 72 | + - 在 ShellLayer 上创建背景子 Widget 或直接绘制 |
| 73 | +- [ ] `onGeometryChanged()` 中: |
| 74 | + - 更新背景区域尺寸 |
| 75 | + - 触发重绘 |
| 76 | +- [ ] `deactivate()` 中:清理资源 |
| 77 | + |
| 78 | +#### Step 3: 为 ShellLayer 添加背景绘制 |
| 79 | +- [ ] 方案 A (推荐): 在 ShellLayer 的 `paintEvent()` 中绘制纯色背景 |
| 80 | + ```cpp |
| 81 | + void ShellLayer::paintEvent(QPaintEvent*) { |
| 82 | + QPainter p(this); |
| 83 | + auto* theme = ThemeManager::instance().currentTheme(); |
| 84 | + p.fillRect(rect(), theme->colorScheme().surface()); |
| 85 | + } |
| 86 | + ``` |
| 87 | +- [ ] 方案 B: 壁纸图片渲染 |
| 88 | + - 在 `DefaultShellStrategy::activate()` 中加载壁纸 QPixmap |
| 89 | + - 提供 `WallpaperLayer` 子 Widget 或在 paintEvent 中 `drawPixmap()` |
| 90 | +- [ ] 选择配色:使用 ThemeManager 的 `colorScheme().surface()` 作为默认背景色 |
| 91 | +
|
| 92 | +**可复用**: `ui/core/theme_manager.h` (ThemeManager 单例)、`ui/core/color_scheme.h` (颜色方案) |
| 93 | +
|
| 94 | +#### Step 4: 修改 CFDesktopEntity::run_init() 连接所有组件 |
| 95 | +- [ ] 在 `CFDesktopEntity::run_init()` 中(文件 `desktop/ui/CFDesktopEntity.cpp:45`): |
| 96 | + ```cpp |
| 97 | + // 1. 创建 PanelManager |
| 98 | + auto* panel_mgr = new PanelManager(desktop_entity_, desktop_entity_); |
| 99 | +
|
| 100 | + // 2. 创建 ShellLayer |
| 101 | + auto* shell = new ShellLayer(desktop_entity_); |
| 102 | +
|
| 103 | + // 3. 注入到 CFDesktop |
| 104 | + CFDesktop::InitResources res; |
| 105 | + res.panel_manager_ = panel_mgr; |
| 106 | + res.shell_layer_ = shell; |
| 107 | + desktop_entity_->register_desktop_resources(res); |
| 108 | +
|
| 109 | + // 4. 设置 ShellLayer 策略 |
| 110 | + shell->setStrategy(std::make_unique<DefaultShellStrategy>()); |
| 111 | +
|
| 112 | + // 5. 连接 PanelManager geometry 变化到 ShellLayer |
| 113 | + connect(panel_mgr, &PanelManager::availableGeometryChanged, |
| 114 | + shell, &ShellLayer::onAvailableGeometryChanged); |
| 115 | +
|
| 116 | + // 6. 显示 |
| 117 | + desktop_entity_->showFullScreen(); |
| 118 | + ``` |
| 119 | + |
| 120 | +#### Step 5: 确保 CFDesktop 正确接收 geometry |
| 121 | +- [ ] 在 `CFDesktop::register_desktop_resources()` 中(文件 `desktop/ui/CFDesktop.cpp:21`): |
| 122 | + - 验证 `panel_manager_` 和 `shell_layer_` 非空 |
| 123 | + - 触发 PanelManager 初始布局计算 |
| 124 | + |
| 125 | +#### Step 6: 更新 CMakeLists.txt |
| 126 | +- [ ] 在 `desktop/ui/components/CMakeLists.txt` 中添加 `ShellLayer.cpp` |
| 127 | +- [ ] 如新建 strategy 目录,确保 CMake 能发现新文件 |
| 128 | + |
| 129 | +--- |
| 130 | + |
| 131 | +### Day 2: 验证与调试 |
| 132 | + |
| 133 | +#### Step 7: 构建并运行 |
| 134 | +- [ ] `cmake --build build` 确认编译通过 |
| 135 | +- [ ] 运行后验证: |
| 136 | + - [ ] 桌面全屏显示 |
| 137 | + - [ ] 背景非空白(纯色或壁纸) |
| 138 | + - [ ] 关闭后无 crash / 内存泄漏 |
| 139 | + |
| 140 | +#### Step 8: 调试布局 |
| 141 | +- [ ] 在 PanelManager::relayout() 中添加 debug log 输出 `availableGeometry()` |
| 142 | +- [ ] 确认 ShellLayer 的 geometry 正确跟随屏幕大小 |
| 143 | +- [ ] 确认后续注册 Panel 后 availableGeometry 会正确缩小 |
| 144 | + |
| 145 | +--- |
| 146 | + |
| 147 | +## 四、关键文件清单 |
| 148 | + |
| 149 | +### 需要修改的文件 |
| 150 | +| 文件 | 修改内容 | |
| 151 | +|------|----------| |
| 152 | +| `desktop/ui/CFDesktopEntity.cpp` | `run_init()` 中创建 ShellLayer、PanelManager、设置策略、show | |
| 153 | +| `desktop/ui/components/CMakeLists.txt` | 添加 ShellLayer.cpp | |
| 154 | + |
| 155 | +### 需要新建的文件 |
| 156 | +| 文件 | 内容 | |
| 157 | +|------|------| |
| 158 | +| `desktop/ui/components/ShellLayer.cpp` | ShellLayer 实现 | |
| 159 | +| `desktop/ui/strategy/default_shell_strategy.h` | 默认 Shell 策略头文件 | |
| 160 | +| `desktop/ui/strategy/default_shell_strategy.cpp` | 默认 Shell 策略实现 | |
| 161 | + |
| 162 | +### 参考文件 (只读) |
| 163 | +| 文件 | 用途 | |
| 164 | +|------|------| |
| 165 | +| `desktop/ui/CFDesktop.h:76-81` | `InitResources` 结构体 | |
| 166 | +| `desktop/ui/CFDesktop.cpp:21-25` | `register_desktop_resources()` | |
| 167 | +| `desktop/ui/components/PanelManager.h` | PanelManager 接口 | |
| 168 | +| `desktop/ui/components/IShellLayerStrategy.h` | 策略接口 | |
| 169 | +| `desktop/ui/widget/init_session/simple_boot_widget.cpp` | QPainter 绘制参考 | |
| 170 | +| `ui/core/theme_manager.h` | ThemeManager 单例 | |
| 171 | + |
| 172 | +--- |
| 173 | + |
| 174 | +## 五、验收标准 |
| 175 | + |
| 176 | +- [ ] `./scripts/run.sh` 后看到全屏非空白桌面 |
| 177 | +- [ ] 桌面背景色跟随 ThemeManager 的 surface 色值 |
| 178 | +- [ ] PanelManager 的 `availableGeometry()` 返回正确值 (初始为全屏) |
| 179 | +- [ ] 后续注册 Panel 后 `availableGeometry()` 会自动缩小 |
| 180 | +- [ ] 关闭后无内存泄漏 |
| 181 | + |
| 182 | +--- |
| 183 | + |
| 184 | +*最后更新: 2026-03-31* |
0 commit comments