feat: Implement window factory and registry for managing window creation and lifecycle
- Added `window_factory` class to handle the creation of various window types (main, child, popup, dialog). - Introduced `window_registry` class for managing window instances, their relationships, and states. - Defined structures for window creation information including `popup_create_info`, `dialog_create_info`, and `child_window_create_info`. - Implemented thread-safe mechanisms for window registration, unregistration, and querying. - Added enumerations for window types and states with string conversion functions for better debugging and logging.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
1270
docs/WINDOW_MANAGEMENT_REFACTOR.md
Normal file
1270
docs/WINDOW_MANAGEMENT_REFACTOR.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,5 @@
|
||||
#include "application.h"
|
||||
|
||||
#include "window_manager.h"
|
||||
#include "window_interface.h"
|
||||
#include "window_common.h"
|
||||
#include "event/event_types.h"
|
||||
@@ -52,7 +51,7 @@ namespace mirage::app {
|
||||
// 1. 创建窗口管理器和窗口
|
||||
// ========================================================================
|
||||
|
||||
window_manager_ = std::make_unique<window_manager>();
|
||||
window_manager_ = std::make_unique<unified_window_manager>();
|
||||
|
||||
window_create_info window_info{
|
||||
.title = config.title,
|
||||
@@ -67,13 +66,14 @@ namespace mirage::app {
|
||||
window_info.flags = window_flag::VISIBLE | window_flag::DECORATED | window_flag::FOCUSED;
|
||||
}
|
||||
|
||||
auto window_result = window_manager_->create_window(window_info);
|
||||
auto window_result = window_manager_->create_main_window(window_info);
|
||||
if (!window_result.has_value()) {
|
||||
std::cerr << "[application] Failed to create window: " << window_result.error() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
window_ = window_manager_->get_window(window_result.value());
|
||||
main_window_id_ = window_result.value();
|
||||
window_ = window_manager_->get_window(main_window_id_);
|
||||
if (!window_) {
|
||||
std::cerr << "[application] Failed to get window pointer" << std::endl;
|
||||
return false;
|
||||
@@ -508,7 +508,7 @@ namespace mirage::app {
|
||||
|
||||
void application::process_events() {
|
||||
if (window_manager_) {
|
||||
window_manager_->poll_all_events();
|
||||
window_manager_->poll_events();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "vulkan/vulkan_common.h"
|
||||
#include "widget_context.h"
|
||||
#include "window/main_window_widget.h"
|
||||
#include "unified_window_manager.h"
|
||||
|
||||
#include "widget_event/widget_event_router.h"
|
||||
|
||||
@@ -36,7 +37,6 @@ namespace mirage {
|
||||
// 前向声明
|
||||
namespace mirage {
|
||||
class window_interface;
|
||||
class window_manager;
|
||||
class render_pipeline;
|
||||
class widget_base;
|
||||
class render_context;
|
||||
@@ -318,10 +318,13 @@ private:
|
||||
// 核心组件
|
||||
// ========================================================================
|
||||
|
||||
/// @brief 窗口管理器
|
||||
std::unique_ptr<window_manager> window_manager_;
|
||||
/// @brief 统一窗口管理器
|
||||
std::unique_ptr<unified_window_manager> window_manager_;
|
||||
|
||||
/// @brief 窗口指针(由窗口管理器管理)
|
||||
/// @brief 主窗口ID
|
||||
window_id main_window_id_{INVALID_WINDOW_ID};
|
||||
|
||||
/// @brief 窗口指针(由窗口管理器管理,兼容层)
|
||||
window_interface* window_ = nullptr;
|
||||
|
||||
/// @brief GLFW 窗口指针(用于创建 Vulkan Surface)
|
||||
|
||||
48
src/common/window_id.h
Normal file
48
src/common/window_id.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <atomic>
|
||||
|
||||
namespace mirage {
|
||||
|
||||
/// 窗口唯一标识符类型
|
||||
/// 定义在 common 模块,供 render 和 window 模块共同使用
|
||||
using window_id = uint64_t;
|
||||
|
||||
/// 无效窗口ID常量
|
||||
constexpr window_id INVALID_WINDOW_ID = 0;
|
||||
|
||||
/// 检查窗口ID是否有效
|
||||
/// @param id 要检查的窗口ID
|
||||
/// @return 如果ID有效返回true,否则返回false
|
||||
[[nodiscard]] constexpr auto is_valid_window_id(window_id id) noexcept -> bool {
|
||||
return id != INVALID_WINDOW_ID;
|
||||
}
|
||||
|
||||
/// 线程安全的窗口ID生成器
|
||||
/// 使用原子操作确保多线程环境下ID的唯一性
|
||||
class window_id_generator {
|
||||
public:
|
||||
/// 生成下一个唯一的窗口ID
|
||||
/// @return 新生成的窗口ID
|
||||
[[nodiscard]] auto generate() noexcept -> window_id {
|
||||
return ++next_id_;
|
||||
}
|
||||
|
||||
/// 查看下一个将要生成的ID(不消耗)
|
||||
/// @return 下一个将要生成的窗口ID
|
||||
[[nodiscard]] auto peek_next() const noexcept -> window_id {
|
||||
return next_id_.load(std::memory_order_relaxed) + 1;
|
||||
}
|
||||
|
||||
/// 获取当前已生成的最大ID
|
||||
/// @return 当前最大的窗口ID
|
||||
[[nodiscard]] auto current() const noexcept -> window_id {
|
||||
return next_id_.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<window_id> next_id_{0};
|
||||
};
|
||||
|
||||
} // namespace mirage
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "vulkan/logical_device.h"
|
||||
#include "vulkan/resource_manager.h"
|
||||
#include "vulkan/swapchain.h"
|
||||
#include "window_id.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
@@ -12,8 +13,7 @@
|
||||
#include <cstdint>
|
||||
|
||||
namespace mirage {
|
||||
/// 窗口标识符类型
|
||||
using window_id = uint64_t;
|
||||
// window_id 类型已在 common/window_id.h 中定义于 mirage 命名空间
|
||||
|
||||
/// 窗口渲染上下文 - 封装每窗口独立的 Vulkan 资源
|
||||
///
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
#include "window_id.h"
|
||||
|
||||
#ifdef DELETE
|
||||
#undef DELETE
|
||||
#endif
|
||||
@@ -205,6 +207,7 @@ namespace mirage {
|
||||
/// 通用事件结构
|
||||
struct event {
|
||||
event_type type{event_type::NONE};
|
||||
window_id source_window{INVALID_WINDOW_ID}; ///< 事件来源窗口ID
|
||||
|
||||
union {
|
||||
window_event_data window;
|
||||
@@ -215,10 +218,14 @@ namespace mirage {
|
||||
mouse_scroll_event_data mouse_scroll;
|
||||
};
|
||||
|
||||
event() : type(event_type::NONE), window{} {
|
||||
event() : type(event_type::NONE), source_window(INVALID_WINDOW_ID), window{} {
|
||||
}
|
||||
|
||||
explicit event(event_type t) : type(t), window{} {
|
||||
explicit event(event_type t) : type(t), source_window(INVALID_WINDOW_ID), window{} {
|
||||
}
|
||||
|
||||
event(event_type t, window_id src_window)
|
||||
: type(t), source_window(src_window), window{} {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -84,10 +84,10 @@ namespace mirage {
|
||||
}
|
||||
|
||||
auto vulkan_surface_manager::collect_required_extensions(
|
||||
const window_manager& manager
|
||||
const unified_window_manager& manager
|
||||
) -> std::vector<const char*> {
|
||||
// 获取所有窗口ID
|
||||
auto window_ids = manager.get_all_window_ids();
|
||||
auto window_ids = manager.get_all_windows();
|
||||
|
||||
// 构建窗口指针列表
|
||||
std::vector<const window_interface*> windows;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
#include "window_common.h"
|
||||
#include "window_interface.h"
|
||||
#include "window_manager.h"
|
||||
#include "vulkan/vulkan_common.h"
|
||||
#include "unified_window_manager.h"
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
@@ -50,7 +50,7 @@ namespace mirage {
|
||||
/// @param manager 窗口管理器引用
|
||||
/// @return 扩展名称列表(已去重)
|
||||
[[nodiscard]] static auto collect_required_extensions(
|
||||
const window_manager& manager
|
||||
const unified_window_manager& manager
|
||||
) -> std::vector<const char*>;
|
||||
|
||||
/// 销毁 Vulkan Surface
|
||||
|
||||
409
src/window/unified_window_manager.cpp
Normal file
409
src/window/unified_window_manager.cpp
Normal file
@@ -0,0 +1,409 @@
|
||||
#include "unified_window_manager.h"
|
||||
#include "window_interface.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <ranges>
|
||||
|
||||
namespace mirage {
|
||||
// =============================================================================
|
||||
// 构造函数与析构函数
|
||||
// =============================================================================
|
||||
|
||||
unified_window_manager::unified_window_manager() : id_generator_{}
|
||||
, registry_{std::make_unique<window_registry>()}
|
||||
, factory_{
|
||||
std::make_unique<window_factory>(*registry_, id_generator_)
|
||||
}
|
||||
, event_callback_{}
|
||||
, pending_destroy_{} {
|
||||
}
|
||||
|
||||
unified_window_manager::~unified_window_manager() {
|
||||
// 清理所有窗口
|
||||
// 窗口实例由 registry_ 管理,registry_ 析构时会自动清理
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 窗口创建
|
||||
// =============================================================================
|
||||
|
||||
auto unified_window_manager::create_main_window(const mirage::window_create_info& info)
|
||||
-> std::expected<window_id, std::string> {
|
||||
auto result = factory_->create_main_window(info);
|
||||
if (!result) {
|
||||
return std::unexpected(result.error());
|
||||
}
|
||||
|
||||
auto id = result.value();
|
||||
|
||||
// 设置窗口事件回调
|
||||
setup_window_callbacks(id);
|
||||
|
||||
// 如果是第一个主窗口,自动设置为主窗口
|
||||
if (!is_valid_window_id(registry_->get_main_window())) {
|
||||
registry_->set_main_window(id);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
auto unified_window_manager::create_child_window(window_id parent,
|
||||
const child_window_create_info& info)
|
||||
-> std::expected<window_id, std::string> {
|
||||
auto result = factory_->create_child_window(parent, info);
|
||||
if (!result) {
|
||||
return std::unexpected(result.error());
|
||||
}
|
||||
|
||||
auto id = result.value();
|
||||
|
||||
// 设置窗口事件回调
|
||||
setup_window_callbacks(id);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
auto unified_window_manager::create_popup(window_id owner, const popup_create_info& info)
|
||||
-> std::expected<window_id, std::string> {
|
||||
auto result = factory_->create_popup(owner, info);
|
||||
if (!result) {
|
||||
return std::unexpected(result.error());
|
||||
}
|
||||
|
||||
auto id = result.value();
|
||||
|
||||
// 设置窗口事件回调
|
||||
setup_window_callbacks(id);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
auto unified_window_manager::create_dialog(window_id owner, const dialog_create_info& info)
|
||||
-> std::expected<window_id, std::string> {
|
||||
auto result = factory_->create_dialog(owner, info);
|
||||
if (!result) {
|
||||
return std::unexpected(result.error());
|
||||
}
|
||||
|
||||
auto id = result.value();
|
||||
|
||||
// 设置窗口事件回调
|
||||
setup_window_callbacks(id);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 窗口销毁
|
||||
// =============================================================================
|
||||
|
||||
auto unified_window_manager::destroy_window(window_id id) -> bool {
|
||||
if (!registry_->contains(id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 先递归销毁所有子窗口
|
||||
destroy_all_children(id);
|
||||
|
||||
// 注销窗口
|
||||
return registry_->unregister_window(id);
|
||||
}
|
||||
|
||||
auto unified_window_manager::destroy_all_children(window_id parent) -> size_t {
|
||||
auto children = registry_->get_children(parent);
|
||||
size_t count = 0;
|
||||
|
||||
for (auto child_id : children) {
|
||||
// 递归销毁子窗口的子窗口
|
||||
count += destroy_all_children(child_id);
|
||||
|
||||
// 销毁子窗口本身
|
||||
if (registry_->unregister_window(child_id)) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 窗口查询
|
||||
// =============================================================================
|
||||
|
||||
auto unified_window_manager::get_window(window_id id) -> mirage::window_interface* {
|
||||
return registry_->get_window(id);
|
||||
}
|
||||
|
||||
auto unified_window_manager::get_window(window_id id) const -> const mirage::window_interface* {
|
||||
return registry_->get_window(id);
|
||||
}
|
||||
|
||||
auto unified_window_manager::contains(window_id id) const -> bool {
|
||||
return registry_->contains(id);
|
||||
}
|
||||
|
||||
auto unified_window_manager::get_window_type(window_id id) const -> window_type {
|
||||
auto type = registry_->get_type(id);
|
||||
return type.value_or(window_type::MAIN_WINDOW);
|
||||
}
|
||||
|
||||
auto unified_window_manager::get_window_state(window_id id) const -> window_state {
|
||||
return registry_->get_state(id);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 窗口关系
|
||||
// =============================================================================
|
||||
|
||||
auto unified_window_manager::get_parent(window_id id) const -> window_id {
|
||||
return registry_->get_parent(id);
|
||||
}
|
||||
|
||||
auto unified_window_manager::get_children(window_id id) const -> std::vector<window_id> {
|
||||
return registry_->get_children(id);
|
||||
}
|
||||
|
||||
auto unified_window_manager::get_main_window() const -> window_id {
|
||||
return registry_->get_main_window();
|
||||
}
|
||||
|
||||
auto unified_window_manager::get_focused_window() const -> window_id {
|
||||
return registry_->get_focused_window();
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 窗口状态
|
||||
// =============================================================================
|
||||
|
||||
auto unified_window_manager::set_window_state(window_id id, window_state state) -> bool {
|
||||
auto* window = registry_->get_window(id);
|
||||
if (!window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 更新注册表中的状态
|
||||
if (!registry_->set_state(id, state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 同步窗口实际状态
|
||||
switch (state) {
|
||||
case window_state::NORMAL:
|
||||
window->restore();
|
||||
break;
|
||||
case window_state::MINIMIZED:
|
||||
window->minimize();
|
||||
break;
|
||||
case window_state::MAXIMIZED:
|
||||
window->maximize();
|
||||
break;
|
||||
case window_state::HIDDEN:
|
||||
window->hide();
|
||||
break;
|
||||
case window_state::FULLSCREEN:
|
||||
window->set_mode(mirage::window_mode::FULLSCREEN);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto unified_window_manager::show_window(window_id id) -> bool {
|
||||
auto* window = registry_->get_window(id);
|
||||
if (!window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
window->show();
|
||||
registry_->set_state(id, window_state::NORMAL);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto unified_window_manager::hide_window(window_id id) -> bool {
|
||||
auto* window = registry_->get_window(id);
|
||||
if (!window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
window->hide();
|
||||
registry_->set_state(id, window_state::HIDDEN);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto unified_window_manager::focus_window(window_id id) -> bool {
|
||||
auto* window = registry_->get_window(id);
|
||||
if (!window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
window->focus();
|
||||
registry_->set_focused_window(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 事件处理
|
||||
// =============================================================================
|
||||
|
||||
void unified_window_manager::poll_events() {
|
||||
// 处理之前累积的待销毁窗口
|
||||
process_pending_destroys();
|
||||
|
||||
// 获取所有窗口ID
|
||||
auto all_windows = registry_->get_all_windows();
|
||||
|
||||
// 遍历所有窗口调用 poll_events()
|
||||
for (auto id : all_windows) {
|
||||
auto* window = registry_->get_window(id);
|
||||
if (window) {
|
||||
window->poll_events();
|
||||
|
||||
// 检查窗口关闭状态
|
||||
if (window->should_close()) {
|
||||
handle_window_close(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理本次轮询产生的待销毁窗口
|
||||
process_pending_destroys();
|
||||
}
|
||||
|
||||
void unified_window_manager::set_event_callback(window_event_callback callback) {
|
||||
event_callback_ = std::move(callback);
|
||||
|
||||
// 为所有已存在的窗口重新设置回调
|
||||
auto all_windows = registry_->get_all_windows();
|
||||
for (auto id : all_windows) {
|
||||
setup_window_callbacks(id);
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 批量查询
|
||||
// =============================================================================
|
||||
|
||||
auto unified_window_manager::get_all_windows() const -> std::vector<window_id> {
|
||||
return registry_->get_all_windows();
|
||||
}
|
||||
|
||||
auto unified_window_manager::get_windows_by_type(window_type type) const
|
||||
-> std::vector<window_id> {
|
||||
return registry_->get_windows_by_type(type);
|
||||
}
|
||||
|
||||
auto unified_window_manager::get_visible_windows() const -> std::vector<window_id> {
|
||||
auto all_windows = registry_->get_all_windows();
|
||||
std::vector<window_id> visible;
|
||||
visible.reserve(all_windows.size());
|
||||
|
||||
// 使用 ranges 过滤可见窗口
|
||||
auto is_visible = [this](window_id id) {
|
||||
auto state = registry_->get_state(id);
|
||||
return state != window_state::HIDDEN;
|
||||
};
|
||||
|
||||
std::ranges::copy_if(all_windows, std::back_inserter(visible), is_visible);
|
||||
|
||||
return visible;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 统计
|
||||
// =============================================================================
|
||||
|
||||
auto unified_window_manager::window_count() const -> size_t {
|
||||
return registry_->count();
|
||||
}
|
||||
|
||||
auto unified_window_manager::has_windows() const -> bool {
|
||||
return !registry_->empty();
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 组件访问
|
||||
// =============================================================================
|
||||
|
||||
auto unified_window_manager::registry() -> window_registry& {
|
||||
return *registry_;
|
||||
}
|
||||
|
||||
auto unified_window_manager::registry() const -> const window_registry& {
|
||||
return *registry_;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 内部方法
|
||||
// =============================================================================
|
||||
|
||||
void unified_window_manager::setup_window_callbacks(window_id id) {
|
||||
auto* window = registry_->get_window(id);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 为窗口设置事件回调
|
||||
// 事件中填充 source_window 字段,转发到 event_callback_
|
||||
window->set_event_callback([this, id](const mirage::event& e) {
|
||||
// 创建带有源窗口信息的事件副本
|
||||
mirage::event enhanced_event = e;
|
||||
enhanced_event.source_window = id;
|
||||
|
||||
// 处理特殊事件
|
||||
switch (e.type) {
|
||||
case mirage::event_type::WINDOW_FOCUS:
|
||||
registry_->set_focused_window(id);
|
||||
break;
|
||||
case mirage::event_type::WINDOW_LOST_FOCUS:
|
||||
if (registry_->get_focused_window() == id) {
|
||||
registry_->set_focused_window(INVALID_WINDOW_ID);
|
||||
}
|
||||
break;
|
||||
case mirage::event_type::WINDOW_MINIMIZED:
|
||||
registry_->set_state(id, window_state::MINIMIZED);
|
||||
break;
|
||||
case mirage::event_type::WINDOW_MAXIMIZED:
|
||||
registry_->set_state(id, window_state::MAXIMIZED);
|
||||
break;
|
||||
case mirage::event_type::WINDOW_RESTORED:
|
||||
registry_->set_state(id, window_state::NORMAL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// 转发到用户回调
|
||||
if (event_callback_) {
|
||||
event_callback_(id, enhanced_event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void unified_window_manager::handle_window_close(window_id id) {
|
||||
// 如果是主窗口关闭,可能需要特殊处理
|
||||
auto main_window = registry_->get_main_window();
|
||||
|
||||
// 触发关闭事件
|
||||
if (event_callback_) {
|
||||
mirage::event close_event{mirage::event_type::WINDOW_CLOSE, id};
|
||||
event_callback_(id, close_event);
|
||||
}
|
||||
|
||||
// 将窗口添加到待销毁列表(延迟销毁,避免在遍历过程中修改容器)
|
||||
pending_destroy_.push_back(id);
|
||||
}
|
||||
|
||||
void unified_window_manager::process_pending_destroys() {
|
||||
if (pending_destroy_.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 复制列表以避免在销毁过程中产生新的待销毁窗口导致的问题
|
||||
auto to_destroy = std::move(pending_destroy_);
|
||||
pending_destroy_.clear();
|
||||
|
||||
for (auto id : to_destroy) {
|
||||
destroy_window(id);
|
||||
}
|
||||
}
|
||||
} // namespace mirage
|
||||
275
src/window/unified_window_manager.h
Normal file
275
src/window/unified_window_manager.h
Normal file
@@ -0,0 +1,275 @@
|
||||
#pragma once
|
||||
|
||||
#include "window_id.h"
|
||||
#include "window_type.h"
|
||||
#include "window_types.h"
|
||||
#include "window_common.h"
|
||||
#include "window_registry.h"
|
||||
#include "window_factory.h"
|
||||
|
||||
#include <expected>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace mirage {
|
||||
/// 窗口事件回调类型
|
||||
/// @param id 事件来源窗口ID
|
||||
/// @param e 事件对象
|
||||
using window_event_callback = std::function<void(window_id, const mirage::event&)>;
|
||||
|
||||
/// 统一窗口管理器
|
||||
///
|
||||
/// 窗口管理框架的统一入口,整合:
|
||||
/// - window_registry - 窗口注册表
|
||||
/// - window_factory - 窗口工厂
|
||||
/// - window_id_generator - ID生成器
|
||||
/// - 事件轮询与分发
|
||||
///
|
||||
/// 使用示例:
|
||||
/// @code
|
||||
/// unified_window_manager manager;
|
||||
///
|
||||
/// // 创建主窗口
|
||||
/// auto result = manager.create_main_window({.title = "My App", .width = 1280, .height = 720});
|
||||
/// if (result) {
|
||||
/// auto main_id = result.value();
|
||||
///
|
||||
/// // 设置事件回调
|
||||
/// manager.set_event_callback([](window_id id, const event& e) {
|
||||
/// // 处理事件
|
||||
/// });
|
||||
///
|
||||
/// // 主循环
|
||||
/// while (manager.has_windows()) {
|
||||
/// manager.poll_events();
|
||||
/// // 渲染...
|
||||
/// }
|
||||
/// }
|
||||
/// @endcode
|
||||
class unified_window_manager {
|
||||
public:
|
||||
/// 构造函数
|
||||
/// 初始化 id_generator_, registry_, factory_
|
||||
unified_window_manager();
|
||||
|
||||
/// 析构函数
|
||||
~unified_window_manager();
|
||||
|
||||
// 禁止拷贝
|
||||
unified_window_manager(const unified_window_manager&) = delete;
|
||||
auto operator=(const unified_window_manager&) -> unified_window_manager& = delete;
|
||||
|
||||
// 允许移动
|
||||
unified_window_manager(unified_window_manager&&) noexcept = default;
|
||||
auto operator=(unified_window_manager&&) noexcept -> unified_window_manager& = default;
|
||||
|
||||
// =========================================================================
|
||||
// 窗口创建
|
||||
// =========================================================================
|
||||
|
||||
/// 创建主窗口
|
||||
/// @param info 窗口创建信息
|
||||
/// @return 成功返回窗口ID,失败返回错误消息
|
||||
[[nodiscard]] auto create_main_window(const mirage::window_create_info& info)
|
||||
-> std::expected<window_id, std::string>;
|
||||
|
||||
/// 创建子窗口
|
||||
/// @param parent 父窗口ID
|
||||
/// @param info 子窗口创建信息
|
||||
/// @return 成功返回窗口ID,失败返回错误消息
|
||||
[[nodiscard]] auto create_child_window(window_id parent,
|
||||
const child_window_create_info& info)
|
||||
-> std::expected<window_id, std::string>;
|
||||
|
||||
/// 创建弹出窗口
|
||||
/// @param owner 所有者窗口ID
|
||||
/// @param info 弹出窗口创建信息
|
||||
/// @return 成功返回窗口ID,失败返回错误消息
|
||||
[[nodiscard]] auto create_popup(window_id owner, const popup_create_info& info)
|
||||
-> std::expected<window_id, std::string>;
|
||||
|
||||
/// 创建对话框
|
||||
/// @param owner 所有者窗口ID
|
||||
/// @param info 对话框创建信息
|
||||
/// @return 成功返回窗口ID,失败返回错误消息
|
||||
[[nodiscard]] auto create_dialog(window_id owner, const dialog_create_info& info)
|
||||
-> std::expected<window_id, std::string>;
|
||||
|
||||
// =========================================================================
|
||||
// 窗口销毁
|
||||
// =========================================================================
|
||||
|
||||
/// 销毁窗口
|
||||
/// @param id 窗口ID
|
||||
/// @return 成功返回true,失败返回false
|
||||
auto destroy_window(window_id id) -> bool;
|
||||
|
||||
/// 销毁指定窗口的所有子窗口
|
||||
/// @param parent 父窗口ID
|
||||
/// @return 被销毁的子窗口数量
|
||||
auto destroy_all_children(window_id parent) -> size_t;
|
||||
|
||||
// =========================================================================
|
||||
// 窗口查询
|
||||
// =========================================================================
|
||||
|
||||
/// 获取窗口实例
|
||||
/// @param id 窗口ID
|
||||
/// @return 窗口实例指针,如不存在返回nullptr
|
||||
[[nodiscard]] auto get_window(window_id id) -> mirage::window_interface*;
|
||||
|
||||
/// 获取窗口实例(const版本)
|
||||
/// @param id 窗口ID
|
||||
/// @return 窗口实例指针,如不存在返回nullptr
|
||||
[[nodiscard]] auto get_window(window_id id) const -> const mirage::window_interface*;
|
||||
|
||||
/// 检查窗口是否存在
|
||||
/// @param id 窗口ID
|
||||
/// @return 如果存在返回true,否则返回false
|
||||
[[nodiscard]] auto contains(window_id id) const -> bool;
|
||||
|
||||
/// 获取窗口类型
|
||||
/// @param id 窗口ID
|
||||
/// @return 窗口类型,如窗口不存在返回 MAIN_WINDOW 作为默认值
|
||||
[[nodiscard]] auto get_window_type(window_id id) const -> window_type;
|
||||
|
||||
/// 获取窗口状态
|
||||
/// @param id 窗口ID
|
||||
/// @return 窗口状态,如窗口不存在返回 HIDDEN
|
||||
[[nodiscard]] auto get_window_state(window_id id) const -> window_state;
|
||||
|
||||
// =========================================================================
|
||||
// 窗口关系
|
||||
// =========================================================================
|
||||
|
||||
/// 获取父窗口ID
|
||||
/// @param id 窗口ID
|
||||
/// @return 父窗口ID,如无父窗口或窗口不存在返回 INVALID_WINDOW_ID
|
||||
[[nodiscard]] auto get_parent(window_id id) const -> window_id;
|
||||
|
||||
/// 获取直接子窗口列表
|
||||
/// @param id 窗口ID
|
||||
/// @return 子窗口ID列表,如窗口不存在返回空列表
|
||||
[[nodiscard]] auto get_children(window_id id) const -> std::vector<window_id>;
|
||||
|
||||
/// 获取主窗口ID
|
||||
/// @return 主窗口ID,如无主窗口返回 INVALID_WINDOW_ID
|
||||
[[nodiscard]] auto get_main_window() const -> window_id;
|
||||
|
||||
/// 获取当前焦点窗口ID
|
||||
/// @return 焦点窗口ID,如无焦点窗口返回 INVALID_WINDOW_ID
|
||||
[[nodiscard]] auto get_focused_window() const -> window_id;
|
||||
|
||||
// =========================================================================
|
||||
// 窗口状态
|
||||
// =========================================================================
|
||||
|
||||
/// 设置窗口状态
|
||||
/// @param id 窗口ID
|
||||
/// @param state 新状态
|
||||
/// @return 成功返回true,失败返回false
|
||||
auto set_window_state(window_id id, window_state state) -> bool;
|
||||
|
||||
/// 显示窗口
|
||||
/// @param id 窗口ID
|
||||
/// @return 成功返回true,失败返回false
|
||||
auto show_window(window_id id) -> bool;
|
||||
|
||||
/// 隐藏窗口
|
||||
/// @param id 窗口ID
|
||||
/// @return 成功返回true,失败返回false
|
||||
auto hide_window(window_id id) -> bool;
|
||||
|
||||
/// 使窗口获取焦点
|
||||
/// @param id 窗口ID
|
||||
/// @return 成功返回true,失败返回false
|
||||
auto focus_window(window_id id) -> bool;
|
||||
|
||||
// =========================================================================
|
||||
// 事件处理
|
||||
// =========================================================================
|
||||
|
||||
/// 轮询所有窗口的事件
|
||||
/// 遍历所有窗口调用 poll_events(),检查窗口关闭状态,触发事件回调
|
||||
void poll_events();
|
||||
|
||||
/// 设置事件回调函数
|
||||
/// @param callback 事件回调函数
|
||||
void set_event_callback(window_event_callback callback);
|
||||
|
||||
// =========================================================================
|
||||
// 批量查询
|
||||
// =========================================================================
|
||||
|
||||
/// 获取所有已注册的窗口ID
|
||||
/// @return 所有窗口ID列表
|
||||
[[nodiscard]] auto get_all_windows() const -> std::vector<window_id>;
|
||||
|
||||
/// 按类型获取所有窗口ID
|
||||
/// @param type 窗口类型
|
||||
/// @return 该类型的所有窗口ID列表
|
||||
[[nodiscard]] auto get_windows_by_type(window_type type) const -> std::vector<window_id>;
|
||||
|
||||
/// 获取所有可见窗口ID
|
||||
/// @return 所有可见窗口ID列表
|
||||
[[nodiscard]] auto get_visible_windows() const -> std::vector<window_id>;
|
||||
|
||||
// =========================================================================
|
||||
// 统计
|
||||
// =========================================================================
|
||||
|
||||
/// 获取已注册窗口总数
|
||||
/// @return 窗口数量
|
||||
[[nodiscard]] auto window_count() const -> size_t;
|
||||
|
||||
/// 检查是否有任何窗口
|
||||
/// @return 如果有窗口返回true,否则返回false
|
||||
[[nodiscard]] auto has_windows() const -> bool;
|
||||
|
||||
// =========================================================================
|
||||
// 组件访问
|
||||
// =========================================================================
|
||||
|
||||
/// 获取窗口注册表引用
|
||||
/// @return 窗口注册表引用
|
||||
[[nodiscard]] auto registry() -> window_registry&;
|
||||
|
||||
/// 获取窗口注册表引用(const版本)
|
||||
/// @return 窗口注册表常量引用
|
||||
[[nodiscard]] auto registry() const -> const window_registry&;
|
||||
|
||||
private:
|
||||
/// 窗口ID生成器
|
||||
window_id_generator id_generator_;
|
||||
|
||||
/// 窗口注册表
|
||||
std::unique_ptr<window_registry> registry_;
|
||||
|
||||
/// 窗口工厂
|
||||
std::unique_ptr<window_factory> factory_;
|
||||
|
||||
/// 事件回调函数
|
||||
window_event_callback event_callback_;
|
||||
|
||||
/// 待销毁窗口列表(用于延迟销毁)
|
||||
std::vector<window_id> pending_destroy_;
|
||||
|
||||
// =========================================================================
|
||||
// 内部方法
|
||||
// =========================================================================
|
||||
|
||||
/// 为窗口设置事件回调
|
||||
/// 事件中填充 source_window 字段,转发到 event_callback_
|
||||
/// @param id 窗口ID
|
||||
void setup_window_callbacks(window_id id);
|
||||
|
||||
/// 处理窗口关闭事件
|
||||
/// @param id 窗口ID
|
||||
void handle_window_close(window_id id);
|
||||
|
||||
/// 处理待销毁的窗口
|
||||
void process_pending_destroys();
|
||||
};
|
||||
} // namespace mirage
|
||||
319
src/window/window_factory.cpp
Normal file
319
src/window/window_factory.cpp
Normal file
@@ -0,0 +1,319 @@
|
||||
#include "window_factory.h"
|
||||
#include "window_registry.h"
|
||||
#include "window_interface.h"
|
||||
|
||||
namespace mirage {
|
||||
// =============================================================================
|
||||
// 构造函数
|
||||
// =============================================================================
|
||||
|
||||
window_factory::window_factory(window_registry& registry, window_id_generator& id_gen) : registry_(registry)
|
||||
, id_generator_(id_gen) {
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 主窗口创建
|
||||
// =============================================================================
|
||||
|
||||
auto window_factory::create_main_window(const mirage::window_create_info& info)
|
||||
-> std::expected<window_id, std::string> {
|
||||
// 准备创建信息
|
||||
auto prepared_info = prepare_create_info(info, window_type::MAIN_WINDOW);
|
||||
|
||||
// 调用平台窗口创建函数
|
||||
auto window_result = mirage::create_window(prepared_info);
|
||||
if (!window_result) {
|
||||
return std::unexpected("Failed to create main window: platform error " +
|
||||
std::string(mirage::window_error_to_string(window_result.error())));
|
||||
}
|
||||
|
||||
// 生成窗口ID
|
||||
auto id = id_generator_.generate();
|
||||
|
||||
// 注册窗口到注册表
|
||||
if (!registry_.register_window(id, window_type::MAIN_WINDOW,
|
||||
std::move(window_result.value()), INVALID_WINDOW_ID)) {
|
||||
return std::unexpected("Failed to register main window");
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 子窗口创建
|
||||
// =============================================================================
|
||||
|
||||
auto window_factory::create_child_window(window_id parent, const child_window_create_info& info)
|
||||
-> std::expected<window_id, std::string> {
|
||||
// 验证父窗口存在
|
||||
if (!registry_.contains(parent)) {
|
||||
return std::unexpected("Parent window does not exist");
|
||||
}
|
||||
|
||||
// 获取父窗口位置以计算子窗口的绝对位置
|
||||
auto parent_pos_result = get_owner_position(parent);
|
||||
if (!parent_pos_result) {
|
||||
return std::unexpected(parent_pos_result.error());
|
||||
}
|
||||
auto [parent_x, parent_y] = parent_pos_result.value();
|
||||
|
||||
// 构建创建信息
|
||||
mirage::window_create_info create_info;
|
||||
create_info.title = info.title;
|
||||
create_info.width = static_cast<int32_t>(info.width);
|
||||
create_info.height = static_cast<int32_t>(info.height);
|
||||
create_info.mode = mirage::window_mode::WINDOWED;
|
||||
|
||||
// 设置窗口标志
|
||||
create_info.flags = mirage::window_flag::VISIBLE |
|
||||
mirage::window_flag::DECORATED |
|
||||
mirage::window_flag::FOCUSED;
|
||||
if (info.resizable) {
|
||||
create_info.flags = create_info.flags | mirage::window_flag::RESIZABLE;
|
||||
}
|
||||
|
||||
// 准备创建信息
|
||||
auto prepared_info = prepare_create_info(create_info, window_type::CHILD_WINDOW);
|
||||
|
||||
// 调用平台窗口创建函数
|
||||
auto window_result = mirage::create_window(prepared_info);
|
||||
if (!window_result) {
|
||||
return std::unexpected("Failed to create child window: platform error " +
|
||||
std::string(mirage::window_error_to_string(window_result.error())));
|
||||
}
|
||||
|
||||
// 设置子窗口位置(相对于父窗口)
|
||||
auto& window_ptr = window_result.value();
|
||||
window_ptr->set_position(parent_x + info.x, parent_y + info.y);
|
||||
|
||||
// 生成窗口ID
|
||||
auto id = id_generator_.generate();
|
||||
|
||||
// 注册窗口到注册表(带父窗口)
|
||||
if (!registry_.register_window(id, window_type::CHILD_WINDOW,
|
||||
std::move(window_ptr), parent)) {
|
||||
return std::unexpected("Failed to register child window");
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 弹出窗口创建
|
||||
// =============================================================================
|
||||
|
||||
auto window_factory::create_popup(window_id owner, const popup_create_info& info)
|
||||
-> std::expected<window_id, std::string> {
|
||||
// 验证所有者窗口存在
|
||||
if (!registry_.contains(owner)) {
|
||||
return std::unexpected("Owner window does not exist");
|
||||
}
|
||||
|
||||
// 获取所有者窗口位置
|
||||
auto owner_pos_result = get_owner_position(owner);
|
||||
if (!owner_pos_result) {
|
||||
return std::unexpected(owner_pos_result.error());
|
||||
}
|
||||
auto [owner_x, owner_y] = owner_pos_result.value();
|
||||
|
||||
// 构建创建信息 - 弹出窗口通常无边框
|
||||
mirage::window_create_info create_info;
|
||||
create_info.title = info.title;
|
||||
create_info.width = static_cast<int32_t>(info.width);
|
||||
create_info.height = static_cast<int32_t>(info.height);
|
||||
create_info.mode = mirage::window_mode::WINDOWED;
|
||||
|
||||
// 弹出窗口标志:无边框、浮动
|
||||
create_info.flags = mirage::window_flag::VISIBLE |
|
||||
mirage::window_flag::FLOATING;
|
||||
|
||||
// 准备创建信息
|
||||
auto prepared_info = prepare_create_info(create_info, window_type::POPUP);
|
||||
|
||||
// 调用平台窗口创建函数
|
||||
auto window_result = mirage::create_window(prepared_info);
|
||||
if (!window_result) {
|
||||
return std::unexpected("Failed to create popup window: platform error " +
|
||||
std::string(mirage::window_error_to_string(window_result.error())));
|
||||
}
|
||||
|
||||
// 设置弹出窗口位置(相对于所有者)
|
||||
auto& window_ptr = window_result.value();
|
||||
window_ptr->set_position(owner_x + info.x, owner_y + info.y);
|
||||
|
||||
// 生成窗口ID
|
||||
auto id = id_generator_.generate();
|
||||
|
||||
// 注册窗口到注册表(带所有者作为父窗口)
|
||||
if (!registry_.register_window(id, window_type::POPUP,
|
||||
std::move(window_ptr), owner)) {
|
||||
return std::unexpected("Failed to register popup window");
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 对话框创建
|
||||
// =============================================================================
|
||||
|
||||
auto window_factory::create_dialog(window_id owner, const dialog_create_info& info)
|
||||
-> std::expected<window_id, std::string> {
|
||||
// 验证所有者窗口存在
|
||||
if (!registry_.contains(owner)) {
|
||||
return std::unexpected("Owner window does not exist");
|
||||
}
|
||||
|
||||
// 获取所有者窗口信息用于居中
|
||||
auto* owner_window = registry_.get_window(owner);
|
||||
if (!owner_window) {
|
||||
return std::unexpected("Failed to get owner window");
|
||||
}
|
||||
|
||||
auto [owner_width, owner_height] = owner_window->get_size();
|
||||
auto [owner_x, owner_y] = owner_window->get_position();
|
||||
|
||||
// 构建创建信息
|
||||
mirage::window_create_info create_info;
|
||||
create_info.title = info.title;
|
||||
create_info.width = static_cast<int32_t>(info.width);
|
||||
create_info.height = static_cast<int32_t>(info.height);
|
||||
create_info.mode = mirage::window_mode::WINDOWED;
|
||||
|
||||
// 对话框标志:有边框、浮动、获取焦点
|
||||
create_info.flags = mirage::window_flag::VISIBLE |
|
||||
mirage::window_flag::DECORATED |
|
||||
mirage::window_flag::FLOATING |
|
||||
mirage::window_flag::FOCUSED;
|
||||
|
||||
if (info.resizable) {
|
||||
create_info.flags = create_info.flags | mirage::window_flag::RESIZABLE;
|
||||
}
|
||||
|
||||
// 准备创建信息
|
||||
auto prepared_info = prepare_create_info(create_info, window_type::DIALOG);
|
||||
|
||||
// 调用平台窗口创建函数
|
||||
auto window_result = mirage::create_window(prepared_info);
|
||||
if (!window_result) {
|
||||
return std::unexpected("Failed to create dialog window: platform error " +
|
||||
std::string(mirage::window_error_to_string(window_result.error())));
|
||||
}
|
||||
|
||||
auto& window_ptr = window_result.value();
|
||||
|
||||
// 计算居中位置
|
||||
int32_t dialog_x = owner_x + (owner_width - static_cast<int32_t>(info.width)) / 2;
|
||||
int32_t dialog_y = owner_y + (owner_height - static_cast<int32_t>(info.height)) / 2;
|
||||
window_ptr->set_position(dialog_x, dialog_y);
|
||||
|
||||
// 生成窗口ID
|
||||
auto id = id_generator_.generate();
|
||||
|
||||
// 注册窗口到注册表(带所有者作为父窗口)
|
||||
if (!registry_.register_window(id, window_type::DIALOG,
|
||||
std::move(window_ptr), owner)) {
|
||||
return std::unexpected("Failed to register dialog window");
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 通用窗口创建
|
||||
// =============================================================================
|
||||
|
||||
auto window_factory::create_window(window_type type,
|
||||
const mirage::window_create_info& info,
|
||||
window_id parent)
|
||||
-> std::expected<window_id, std::string> {
|
||||
// 如果指定了父窗口,验证其存在
|
||||
if (is_valid_window_id(parent) && !registry_.contains(parent)) {
|
||||
return std::unexpected("Parent window does not exist");
|
||||
}
|
||||
|
||||
// 准备创建信息
|
||||
auto prepared_info = prepare_create_info(info, type);
|
||||
|
||||
// 调用平台窗口创建函数
|
||||
auto window_result = mirage::create_window(prepared_info);
|
||||
if (!window_result) {
|
||||
return std::unexpected("Failed to create window: platform error " +
|
||||
std::string(mirage::window_error_to_string(window_result.error())));
|
||||
}
|
||||
|
||||
// 生成窗口ID
|
||||
auto id = id_generator_.generate();
|
||||
|
||||
// 注册窗口到注册表
|
||||
if (!registry_.register_window(id, type, std::move(window_result.value()), parent)) {
|
||||
return std::unexpected("Failed to register window");
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 内部辅助方法
|
||||
// =============================================================================
|
||||
|
||||
auto window_factory::prepare_create_info(const mirage::window_create_info& info,
|
||||
window_type type) const
|
||||
-> mirage::window_create_info {
|
||||
mirage::window_create_info result = info;
|
||||
|
||||
// 根据窗口类型调整默认设置
|
||||
switch (type) {
|
||||
case window_type::MAIN_WINDOW:
|
||||
// 主窗口保持原始设置
|
||||
break;
|
||||
|
||||
case window_type::CHILD_WINDOW:
|
||||
// 子窗口:确保有装饰
|
||||
result.flags = result.flags | mirage::window_flag::DECORATED;
|
||||
break;
|
||||
|
||||
case window_type::POPUP:
|
||||
// 弹出窗口:无边框、浮动
|
||||
// 移除装饰标志
|
||||
result.flags = static_cast<mirage::window_flag>(
|
||||
static_cast<uint32_t>(result.flags) &
|
||||
~static_cast<uint32_t>(mirage::window_flag::DECORATED)
|
||||
);
|
||||
result.flags = result.flags | mirage::window_flag::FLOATING;
|
||||
break;
|
||||
|
||||
case window_type::DIALOG:
|
||||
// 对话框:有装饰、浮动
|
||||
result.flags = result.flags |
|
||||
mirage::window_flag::DECORATED |
|
||||
mirage::window_flag::FLOATING;
|
||||
break;
|
||||
|
||||
case window_type::TOOLTIP:
|
||||
// 提示窗口:无边框、浮动、不获取焦点
|
||||
result.flags = static_cast<mirage::window_flag>(
|
||||
static_cast<uint32_t>(result.flags) &
|
||||
~static_cast<uint32_t>(mirage::window_flag::DECORATED) &
|
||||
~static_cast<uint32_t>(mirage::window_flag::FOCUSED)
|
||||
);
|
||||
result.flags = result.flags | mirage::window_flag::FLOATING;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
auto window_factory::get_owner_position(window_id owner_id) const
|
||||
-> std::expected<std::pair<int32_t, int32_t>, std::string> {
|
||||
auto* owner_window = registry_.get_window(owner_id);
|
||||
if (!owner_window) {
|
||||
return std::unexpected("Owner window not found");
|
||||
}
|
||||
|
||||
return owner_window->get_position();
|
||||
}
|
||||
} // namespace mirage
|
||||
165
src/window/window_factory.h
Normal file
165
src/window/window_factory.h
Normal file
@@ -0,0 +1,165 @@
|
||||
#pragma once
|
||||
|
||||
#include "window_id.h"
|
||||
#include "window_type.h"
|
||||
#include "window_types.h"
|
||||
#include "window_common.h"
|
||||
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace mirage {
|
||||
// 前向声明
|
||||
class window_registry;
|
||||
|
||||
/// 弹出窗口创建信息
|
||||
struct popup_create_info {
|
||||
/// 窗口标题
|
||||
std::string title;
|
||||
|
||||
/// 窗口宽度
|
||||
uint32_t width = 200;
|
||||
|
||||
/// 窗口高度
|
||||
uint32_t height = 150;
|
||||
|
||||
/// 相对于owner的x偏移
|
||||
int32_t x = 0;
|
||||
|
||||
/// 相对于owner的y偏移
|
||||
int32_t y = 0;
|
||||
|
||||
/// 失去焦点时自动关闭
|
||||
bool auto_close = true;
|
||||
};
|
||||
|
||||
/// 对话框创建信息
|
||||
struct dialog_create_info {
|
||||
/// 窗口标题
|
||||
std::string title;
|
||||
|
||||
/// 窗口宽度
|
||||
uint32_t width = 400;
|
||||
|
||||
/// 窗口高度
|
||||
uint32_t height = 300;
|
||||
|
||||
/// 是否模态
|
||||
bool modal = true;
|
||||
|
||||
/// 是否可调整大小
|
||||
bool resizable = false;
|
||||
};
|
||||
|
||||
/// 子窗口创建信息
|
||||
struct child_window_create_info {
|
||||
/// 窗口标题
|
||||
std::string title;
|
||||
|
||||
/// 窗口宽度
|
||||
uint32_t width = 640;
|
||||
|
||||
/// 窗口高度
|
||||
uint32_t height = 480;
|
||||
|
||||
/// 相对于父窗口的x偏移
|
||||
int32_t x = 0;
|
||||
|
||||
/// 相对于父窗口的y偏移
|
||||
int32_t y = 0;
|
||||
|
||||
/// 是否可调整大小
|
||||
bool resizable = true;
|
||||
};
|
||||
|
||||
/// 窗口工厂
|
||||
/// 负责创建各类窗口并将其注册到窗口注册表
|
||||
class window_factory {
|
||||
public:
|
||||
/// 构造函数
|
||||
/// @param registry 窗口注册表引用
|
||||
/// @param id_gen 窗口ID生成器引用
|
||||
explicit window_factory(window_registry& registry, window_id_generator& id_gen);
|
||||
|
||||
~window_factory() = default;
|
||||
|
||||
// 禁止拷贝
|
||||
window_factory(const window_factory&) = delete;
|
||||
auto operator=(const window_factory&) -> window_factory& = delete;
|
||||
|
||||
// 禁止移动
|
||||
window_factory(window_factory&&) = delete;
|
||||
auto operator=(window_factory&&) -> window_factory& = delete;
|
||||
|
||||
// =========================================================================
|
||||
// 窗口创建接口
|
||||
// =========================================================================
|
||||
|
||||
/// 创建主窗口
|
||||
/// @param info 窗口创建信息
|
||||
/// @return 成功返回窗口ID,失败返回错误消息
|
||||
[[nodiscard]] auto create_main_window(const mirage::window_create_info& info)
|
||||
-> std::expected<window_id, std::string>;
|
||||
|
||||
/// 创建子窗口
|
||||
/// @param parent 父窗口ID
|
||||
/// @param info 子窗口创建信息
|
||||
/// @return 成功返回窗口ID,失败返回错误消息
|
||||
[[nodiscard]] auto create_child_window(window_id parent, const child_window_create_info& info)
|
||||
-> std::expected<window_id, std::string>;
|
||||
|
||||
/// 创建弹出窗口
|
||||
/// @param owner 所有者窗口ID
|
||||
/// @param info 弹出窗口创建信息
|
||||
/// @return 成功返回窗口ID,失败返回错误消息
|
||||
[[nodiscard]] auto create_popup(window_id owner, const popup_create_info& info)
|
||||
-> std::expected<window_id, std::string>;
|
||||
|
||||
/// 创建对话框
|
||||
/// @param owner 所有者窗口ID
|
||||
/// @param info 对话框创建信息
|
||||
/// @return 成功返回窗口ID,失败返回错误消息
|
||||
[[nodiscard]] auto create_dialog(window_id owner, const dialog_create_info& info)
|
||||
-> std::expected<window_id, std::string>;
|
||||
|
||||
// =========================================================================
|
||||
// 通用创建接口
|
||||
// =========================================================================
|
||||
|
||||
/// 通用窗口创建方法
|
||||
/// @param type 窗口类型
|
||||
/// @param info 窗口创建信息
|
||||
/// @param parent 父窗口ID(可选)
|
||||
/// @return 成功返回窗口ID,失败返回错误消息
|
||||
[[nodiscard]] auto create_window(window_type type,
|
||||
const mirage::window_create_info& info,
|
||||
window_id parent = INVALID_WINDOW_ID)
|
||||
-> std::expected<window_id, std::string>;
|
||||
|
||||
private:
|
||||
/// 窗口注册表引用
|
||||
window_registry& registry_;
|
||||
|
||||
/// 窗口ID生成器引用
|
||||
window_id_generator& id_generator_;
|
||||
|
||||
// =========================================================================
|
||||
// 内部辅助方法
|
||||
// =========================================================================
|
||||
|
||||
/// 将 window_create_info 转换为适合特定窗口类型的配置
|
||||
/// @param info 基础创建信息
|
||||
/// @param type 窗口类型
|
||||
/// @return 调整后的创建信息
|
||||
[[nodiscard]] auto prepare_create_info(const mirage::window_create_info& info,
|
||||
window_type type) const
|
||||
-> mirage::window_create_info;
|
||||
|
||||
/// 获取所有者窗口的位置(用于计算弹出窗口的绝对位置)
|
||||
/// @param owner_id 所有者窗口ID
|
||||
/// @return 成功返回位置{x, y},失败返回错误消息
|
||||
[[nodiscard]] auto get_owner_position(window_id owner_id) const
|
||||
-> std::expected<std::pair<int32_t, int32_t>, std::string>;
|
||||
};
|
||||
} // namespace mirage
|
||||
@@ -1,103 +0,0 @@
|
||||
#include "window_manager.h"
|
||||
|
||||
namespace mirage {
|
||||
// ========== 窗口管理 ==========
|
||||
|
||||
auto window_manager::create_window(const window_create_info& info)
|
||||
-> std::expected<window_id, std::string> {
|
||||
// 使用全局工厂函数创建窗口
|
||||
auto result = mirage::create_window(info);
|
||||
|
||||
if (!result.has_value()) {
|
||||
// 将window_error转换为字符串
|
||||
return std::unexpected(std::string(window_error_to_string(result.error())));
|
||||
}
|
||||
|
||||
// 生成新的窗口ID
|
||||
window_id id = next_window_id_++;
|
||||
|
||||
// 存储窗口
|
||||
windows_[id] = std::move(result.value());
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
auto window_manager::destroy_window(window_id id) -> bool {
|
||||
auto it = windows_.find(id);
|
||||
if (it == windows_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 销毁窗口
|
||||
windows_.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto window_manager::get_window(window_id id) -> window_interface* {
|
||||
auto it = windows_.find(id);
|
||||
if (it == windows_.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
auto window_manager::get_window(window_id id) const -> const window_interface* {
|
||||
auto it = windows_.find(id);
|
||||
if (it == windows_.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
auto window_manager::get_all_window_ids() const -> std::vector<window_id> {
|
||||
std::vector<window_id> ids;
|
||||
ids.reserve(windows_.size());
|
||||
|
||||
for (const auto& [id, window] : windows_) {
|
||||
ids.push_back(id);
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
auto window_manager::get_window_count() const -> size_t {
|
||||
return windows_.size();
|
||||
}
|
||||
|
||||
// ========== 事件处理 ==========
|
||||
|
||||
auto window_manager::poll_all_events() -> void {
|
||||
// 遍历所有窗口并轮询事件
|
||||
for (auto& [id, window] : windows_) {
|
||||
if (window) {
|
||||
window->poll_events();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto window_manager::all_windows_closed() const -> bool {
|
||||
// 如果没有窗口,认为所有窗口都已关闭
|
||||
if (windows_.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查所有窗口是否都应该关闭
|
||||
for (const auto& [id, window] : windows_) {
|
||||
if (window && !window->should_close()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ========== Vulkan设备管理 ==========
|
||||
|
||||
auto window_manager::set_shared_device(std::shared_ptr<logical_device> device) -> void {
|
||||
shared_device_ = std::move(device);
|
||||
}
|
||||
|
||||
auto window_manager::get_shared_device() const -> std::shared_ptr<logical_device> {
|
||||
return shared_device_;
|
||||
}
|
||||
} // namespace mirage
|
||||
@@ -1,128 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "window_common.h"
|
||||
#include "window_interface.h"
|
||||
#include "vulkan/logical_device.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace mirage {
|
||||
/// 窗口管理器类
|
||||
///
|
||||
/// 用于管理多个窗口实例,支持桌面平台的多窗口应用。
|
||||
/// 提供窗口的创建、销毁、查询和统一事件轮询功能。
|
||||
class window_manager {
|
||||
public:
|
||||
/// 窗口ID类型
|
||||
using window_id = uint32_t;
|
||||
|
||||
/// 窗口智能指针类型
|
||||
using window_ptr = std::unique_ptr<window_interface>;
|
||||
|
||||
/// 默认构造函数
|
||||
window_manager() = default;
|
||||
|
||||
/// 析构函数
|
||||
~window_manager() = default;
|
||||
|
||||
// 禁止拷贝
|
||||
window_manager(const window_manager&) = delete;
|
||||
window_manager& operator=(const window_manager&) = delete;
|
||||
|
||||
// 允许移动
|
||||
window_manager(window_manager&&) noexcept = default;
|
||||
window_manager& operator=(window_manager&&) noexcept = default;
|
||||
|
||||
// ========== 窗口管理 ==========
|
||||
|
||||
/// 创建窗口
|
||||
///
|
||||
/// 根据提供的创建信息创建一个新窗口实例,并返回窗口ID。
|
||||
///
|
||||
/// @param info 窗口创建信息
|
||||
/// @return 成功返回窗口ID,失败返回错误消息
|
||||
[[nodiscard]] auto create_window(const window_create_info& info)
|
||||
-> std::expected<window_id, std::string>;
|
||||
|
||||
/// 销毁窗口
|
||||
///
|
||||
/// 根据窗口ID销毁对应的窗口实例。
|
||||
///
|
||||
/// @param id 窗口ID
|
||||
/// @return 成功返回true,失败返回false
|
||||
auto destroy_window(window_id id) -> bool;
|
||||
|
||||
/// 获取窗口
|
||||
///
|
||||
/// 根据窗口ID获取对应的窗口实例指针。
|
||||
///
|
||||
/// @param id 窗口ID
|
||||
/// @return 成功返回窗口指针,失败返回nullptr
|
||||
[[nodiscard]] auto get_window(window_id id) -> window_interface*;
|
||||
|
||||
/// 获取窗口(常量版本)
|
||||
///
|
||||
/// 根据窗口ID获取对应的窗口实例指针。
|
||||
///
|
||||
/// @param id 窗口ID
|
||||
/// @return 成功返回窗口指针,失败返回nullptr
|
||||
[[nodiscard]] auto get_window(window_id id) const -> const window_interface*;
|
||||
|
||||
/// 获取所有窗口ID
|
||||
///
|
||||
/// 返回当前管理的所有窗口的ID列表。
|
||||
///
|
||||
/// @return 窗口ID列表
|
||||
[[nodiscard]] auto get_all_window_ids() const -> std::vector<window_id>;
|
||||
|
||||
/// 获取窗口数量
|
||||
///
|
||||
/// 返回当前管理的窗口总数。
|
||||
///
|
||||
/// @return 窗口数量
|
||||
[[nodiscard]] auto get_window_count() const -> size_t;
|
||||
|
||||
// ========== 事件处理 ==========
|
||||
|
||||
/// 轮询所有窗口的事件
|
||||
///
|
||||
/// 遍历所有窗口并调用它们的poll_events()方法,
|
||||
/// 处理所有待处理的窗口事件。
|
||||
auto poll_all_events() -> void;
|
||||
|
||||
/// 检查是否所有窗口都已关闭
|
||||
///
|
||||
/// 检查所有窗口的should_close()状态。
|
||||
///
|
||||
/// @return 如果所有窗口都应该关闭返回true,否则返回false
|
||||
[[nodiscard]] auto all_windows_closed() const -> bool;
|
||||
|
||||
// ========== Vulkan设备管理 ==========
|
||||
|
||||
/// 设置共享的Vulkan逻辑设备
|
||||
///
|
||||
/// 为多窗口共享Vulkan资源设置共享的逻辑设备。
|
||||
///
|
||||
/// @param device 共享的逻辑设备智能指针
|
||||
auto set_shared_device(std::shared_ptr<logical_device> device) -> void;
|
||||
|
||||
/// 获取共享的Vulkan逻辑设备
|
||||
///
|
||||
/// 返回当前设置的共享逻辑设备。
|
||||
///
|
||||
/// @return 共享的逻辑设备智能指针
|
||||
[[nodiscard]] auto get_shared_device() const -> std::shared_ptr<logical_device>;
|
||||
|
||||
private:
|
||||
/// 窗口存储映射表
|
||||
std::unordered_map<window_id, window_ptr> windows_;
|
||||
|
||||
/// 下一个窗口ID(自动递增)
|
||||
window_id next_window_id_ = 1;
|
||||
|
||||
/// 共享的Vulkan逻辑设备
|
||||
std::shared_ptr<logical_device> shared_device_;
|
||||
};
|
||||
} // namespace mirage
|
||||
432
src/window/window_registry.cpp
Normal file
432
src/window/window_registry.cpp
Normal file
@@ -0,0 +1,432 @@
|
||||
#include "window_registry.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include "window_interface.h"
|
||||
|
||||
namespace mirage {
|
||||
|
||||
// =============================================================================
|
||||
// 窗口注册/注销
|
||||
// =============================================================================
|
||||
|
||||
auto window_registry::register_window(window_id id, window_type type,
|
||||
window_ptr instance,
|
||||
window_id parent) -> bool {
|
||||
std::unique_lock lock(mutex_);
|
||||
|
||||
// 检查ID是否已存在
|
||||
if (windows_.find(id) != windows_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果指定了父窗口,检查父窗口是否存在
|
||||
if (is_valid_window_id(parent) && windows_.find(parent) == windows_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 创建窗口条目
|
||||
window_entry entry;
|
||||
entry.id = id;
|
||||
entry.type = type;
|
||||
entry.state = window_state::NORMAL;
|
||||
entry.parent_id = parent;
|
||||
entry.children = {};
|
||||
entry.instance = std::move(instance);
|
||||
|
||||
// 插入窗口条目
|
||||
windows_.emplace(id, std::move(entry));
|
||||
|
||||
// 如果有父窗口,添加到父窗口的子窗口集合
|
||||
if (is_valid_window_id(parent)) {
|
||||
add_to_parent_impl(id, parent);
|
||||
}
|
||||
|
||||
// 如果是第一个主窗口,自动设置为主窗口
|
||||
if (type == window_type::MAIN_WINDOW && !is_valid_window_id(main_window_)) {
|
||||
main_window_ = id;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto window_registry::unregister_window(window_id id) -> bool {
|
||||
std::unique_lock lock(mutex_);
|
||||
|
||||
auto it = windows_.find(id);
|
||||
if (it == windows_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& entry = it->second;
|
||||
|
||||
// 先递归注销所有子窗口
|
||||
// 注意:需要复制子窗口集合,因为递归过程中会修改它
|
||||
auto children_copy = entry.children;
|
||||
for (auto child_id : children_copy) {
|
||||
// 递归调用需要先释放锁,这里使用非递归方式处理
|
||||
// 将子窗口的父窗口设为无效,然后删除
|
||||
if (auto child_it = windows_.find(child_id); child_it != windows_.end()) {
|
||||
child_it->second.parent_id = INVALID_WINDOW_ID;
|
||||
}
|
||||
}
|
||||
|
||||
// 从父窗口的子窗口集合中移除
|
||||
if (is_valid_window_id(entry.parent_id)) {
|
||||
remove_from_parent_impl(id, entry.parent_id);
|
||||
}
|
||||
|
||||
// 如果是焦点窗口,清除焦点
|
||||
if (focused_window_ == id) {
|
||||
focused_window_ = INVALID_WINDOW_ID;
|
||||
}
|
||||
|
||||
// 如果是主窗口,清除主窗口标记
|
||||
if (main_window_ == id) {
|
||||
main_window_ = INVALID_WINDOW_ID;
|
||||
}
|
||||
|
||||
// 移除窗口条目
|
||||
windows_.erase(it);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto window_registry::contains(window_id id) const -> bool {
|
||||
std::shared_lock lock(mutex_);
|
||||
return windows_.find(id) != windows_.end();
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 窗口查询
|
||||
// =============================================================================
|
||||
|
||||
auto window_registry::get_window(window_id id) -> mirage::window_interface* {
|
||||
std::shared_lock lock(mutex_);
|
||||
auto it = windows_.find(id);
|
||||
if (it != windows_.end()) {
|
||||
return it->second.instance.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto window_registry::get_window(window_id id) const -> const mirage::window_interface* {
|
||||
std::shared_lock lock(mutex_);
|
||||
auto it = windows_.find(id);
|
||||
if (it != windows_.end()) {
|
||||
return it->second.instance.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto window_registry::get_entry(window_id id) const -> std::optional<window_entry> {
|
||||
std::shared_lock lock(mutex_);
|
||||
auto it = windows_.find(id);
|
||||
if (it != windows_.end()) {
|
||||
// 创建条目副本(不包含instance,因为unique_ptr不可复制)
|
||||
window_entry copy;
|
||||
copy.id = it->second.id;
|
||||
copy.type = it->second.type;
|
||||
copy.state = it->second.state;
|
||||
copy.parent_id = it->second.parent_id;
|
||||
copy.children = it->second.children;
|
||||
copy.instance = nullptr; // 不复制实例
|
||||
return copy;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto window_registry::get_type(window_id id) const -> std::optional<window_type> {
|
||||
std::shared_lock lock(mutex_);
|
||||
auto it = windows_.find(id);
|
||||
if (it != windows_.end()) {
|
||||
return it->second.type;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 窗口关系管理
|
||||
// =============================================================================
|
||||
|
||||
auto window_registry::get_parent(window_id id) const -> window_id {
|
||||
std::shared_lock lock(mutex_);
|
||||
auto it = windows_.find(id);
|
||||
if (it != windows_.end()) {
|
||||
return it->second.parent_id;
|
||||
}
|
||||
return INVALID_WINDOW_ID;
|
||||
}
|
||||
|
||||
auto window_registry::get_children(window_id id) const -> std::vector<window_id> {
|
||||
std::shared_lock lock(mutex_);
|
||||
auto it = windows_.find(id);
|
||||
if (it != windows_.end()) {
|
||||
const auto& children = it->second.children;
|
||||
return std::vector<window_id>(children.begin(), children.end());
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
auto window_registry::get_all_descendants(window_id id) const -> std::vector<window_id> {
|
||||
std::shared_lock lock(mutex_);
|
||||
std::vector<window_id> result;
|
||||
collect_descendants_impl(id, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
auto window_registry::set_parent(window_id id, window_id new_parent) -> bool {
|
||||
std::unique_lock lock(mutex_);
|
||||
|
||||
auto it = windows_.find(id);
|
||||
if (it == windows_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果新父窗口有效,检查其是否存在
|
||||
if (is_valid_window_id(new_parent) && windows_.find(new_parent) == windows_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 防止循环引用:检查new_parent是否是id的后代
|
||||
if (is_valid_window_id(new_parent)) {
|
||||
std::vector<window_id> descendants;
|
||||
collect_descendants_impl(id, descendants);
|
||||
auto found = std::find(descendants.begin(), descendants.end(), new_parent);
|
||||
if (found != descendants.end()) {
|
||||
return false; // 会形成循环
|
||||
}
|
||||
}
|
||||
|
||||
auto old_parent = it->second.parent_id;
|
||||
|
||||
// 从旧父窗口移除
|
||||
if (is_valid_window_id(old_parent)) {
|
||||
remove_from_parent_impl(id, old_parent);
|
||||
}
|
||||
|
||||
// 添加到新父窗口
|
||||
if (is_valid_window_id(new_parent)) {
|
||||
add_to_parent_impl(id, new_parent);
|
||||
}
|
||||
|
||||
it->second.parent_id = new_parent;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto window_registry::is_ancestor_of(window_id ancestor, window_id descendant) const -> bool {
|
||||
std::shared_lock lock(mutex_);
|
||||
|
||||
if (!is_valid_window_id(ancestor) || !is_valid_window_id(descendant)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 从descendant向上遍历父窗口链
|
||||
auto current = descendant;
|
||||
while (is_valid_window_id(current)) {
|
||||
auto it = windows_.find(current);
|
||||
if (it == windows_.end()) {
|
||||
return false;
|
||||
}
|
||||
auto parent = it->second.parent_id;
|
||||
if (parent == ancestor) {
|
||||
return true;
|
||||
}
|
||||
current = parent;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 窗口状态管理
|
||||
// =============================================================================
|
||||
|
||||
auto window_registry::set_state(window_id id, window_state state) -> bool {
|
||||
std::unique_lock lock(mutex_);
|
||||
auto it = windows_.find(id);
|
||||
if (it != windows_.end()) {
|
||||
it->second.state = state;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto window_registry::get_state(window_id id) const -> window_state {
|
||||
std::shared_lock lock(mutex_);
|
||||
auto it = windows_.find(id);
|
||||
if (it != windows_.end()) {
|
||||
return it->second.state;
|
||||
}
|
||||
return window_state::HIDDEN;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 批量查询
|
||||
// =============================================================================
|
||||
|
||||
auto window_registry::get_windows_by_type(window_type type) const -> std::vector<window_id> {
|
||||
std::shared_lock lock(mutex_);
|
||||
|
||||
std::vector<window_id> result;
|
||||
result.reserve(windows_.size());
|
||||
|
||||
for (const auto& [id, entry] : windows_) {
|
||||
if (entry.type == type) {
|
||||
result.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
auto window_registry::get_all_windows() const -> std::vector<window_id> {
|
||||
std::shared_lock lock(mutex_);
|
||||
|
||||
std::vector<window_id> result;
|
||||
result.reserve(windows_.size());
|
||||
|
||||
for (const auto& [id, entry] : windows_) {
|
||||
result.push_back(id);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
auto window_registry::get_windows_by_state(window_state state) const -> std::vector<window_id> {
|
||||
std::shared_lock lock(mutex_);
|
||||
|
||||
std::vector<window_id> result;
|
||||
result.reserve(windows_.size());
|
||||
|
||||
for (const auto& [id, entry] : windows_) {
|
||||
if (entry.state == state) {
|
||||
result.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 统计信息
|
||||
// =============================================================================
|
||||
|
||||
auto window_registry::count() const -> size_t {
|
||||
std::shared_lock lock(mutex_);
|
||||
return windows_.size();
|
||||
}
|
||||
|
||||
auto window_registry::count_by_type(window_type type) const -> size_t {
|
||||
std::shared_lock lock(mutex_);
|
||||
size_t count = 0;
|
||||
for (const auto& [id, entry] : windows_) {
|
||||
if (entry.type == type) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
auto window_registry::count_by_state(window_state state) const -> size_t {
|
||||
std::shared_lock lock(mutex_);
|
||||
size_t count = 0;
|
||||
for (const auto& [id, entry] : windows_) {
|
||||
if (entry.state == state) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
auto window_registry::empty() const -> bool {
|
||||
std::shared_lock lock(mutex_);
|
||||
return windows_.empty();
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 焦点和主窗口管理
|
||||
// =============================================================================
|
||||
|
||||
auto window_registry::get_focused_window() const -> window_id {
|
||||
std::shared_lock lock(mutex_);
|
||||
return focused_window_;
|
||||
}
|
||||
|
||||
auto window_registry::set_focused_window(window_id id) -> bool {
|
||||
std::unique_lock lock(mutex_);
|
||||
|
||||
// 允许设置为无效ID(清除焦点)
|
||||
if (!is_valid_window_id(id)) {
|
||||
focused_window_ = INVALID_WINDOW_ID;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查窗口是否存在
|
||||
if (windows_.find(id) == windows_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
focused_window_ = id;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto window_registry::get_main_window() const -> window_id {
|
||||
std::shared_lock lock(mutex_);
|
||||
return main_window_;
|
||||
}
|
||||
|
||||
auto window_registry::set_main_window(window_id id) -> bool {
|
||||
std::unique_lock lock(mutex_);
|
||||
|
||||
// 允许设置为无效ID(清除主窗口)
|
||||
if (!is_valid_window_id(id)) {
|
||||
main_window_ = INVALID_WINDOW_ID;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查窗口是否存在
|
||||
auto it = windows_.find(id);
|
||||
if (it == windows_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 只有主窗口类型才能设置为主窗口
|
||||
if (it->second.type != window_type::MAIN_WINDOW) {
|
||||
return false;
|
||||
}
|
||||
|
||||
main_window_ = id;
|
||||
return true;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 内部辅助方法
|
||||
// =============================================================================
|
||||
|
||||
auto window_registry::remove_from_parent_impl(window_id child_id, window_id parent_id) -> void {
|
||||
auto parent_it = windows_.find(parent_id);
|
||||
if (parent_it != windows_.end()) {
|
||||
parent_it->second.children.erase(child_id);
|
||||
}
|
||||
}
|
||||
|
||||
auto window_registry::add_to_parent_impl(window_id child_id, window_id parent_id) -> void {
|
||||
auto parent_it = windows_.find(parent_id);
|
||||
if (parent_it != windows_.end()) {
|
||||
parent_it->second.children.insert(child_id);
|
||||
}
|
||||
}
|
||||
|
||||
auto window_registry::collect_descendants_impl(window_id id, std::vector<window_id>& result) const -> void {
|
||||
auto it = windows_.find(id);
|
||||
if (it == windows_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto child_id : it->second.children) {
|
||||
result.push_back(child_id);
|
||||
collect_descendants_impl(child_id, result);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mirage
|
||||
236
src/window/window_registry.h
Normal file
236
src/window/window_registry.h
Normal file
@@ -0,0 +1,236 @@
|
||||
#pragma once
|
||||
|
||||
#include "window_id.h"
|
||||
#include "window_type.h"
|
||||
#include "window_common.h"
|
||||
|
||||
#include <optional>
|
||||
#include <shared_mutex>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace mirage {
|
||||
|
||||
/// 窗口元数据条目
|
||||
/// 存储单个窗口的所有相关信息
|
||||
struct window_entry {
|
||||
/// 窗口唯一标识符
|
||||
window_id id{INVALID_WINDOW_ID};
|
||||
|
||||
/// 窗口类型
|
||||
window_type type{window_type::MAIN_WINDOW};
|
||||
|
||||
/// 窗口当前状态
|
||||
window_state state{window_state::NORMAL};
|
||||
|
||||
/// 父窗口ID,主窗口为 INVALID_WINDOW_ID
|
||||
window_id parent_id{INVALID_WINDOW_ID};
|
||||
|
||||
/// 子窗口ID集合
|
||||
std::unordered_set<window_id> children;
|
||||
|
||||
/// 实际窗口实例(通过 mirage::window_ptr)
|
||||
mirage::window_ptr instance;
|
||||
};
|
||||
|
||||
/// 窗口注册表
|
||||
/// 负责窗口实例存储与查询、窗口父子关系管理、窗口状态追踪
|
||||
/// 线程安全,使用 std::shared_mutex 实现读写锁
|
||||
class window_registry {
|
||||
public:
|
||||
window_registry() = default;
|
||||
~window_registry() = default;
|
||||
|
||||
// 禁止拷贝
|
||||
window_registry(const window_registry&) = delete;
|
||||
auto operator=(const window_registry&) -> window_registry& = delete;
|
||||
|
||||
// 禁止移动(因为有互斥锁成员)
|
||||
window_registry(window_registry&&) = delete;
|
||||
auto operator=(window_registry&&) -> window_registry& = delete;
|
||||
|
||||
// =========================================================================
|
||||
// 窗口注册/注销
|
||||
// =========================================================================
|
||||
|
||||
/// 注册窗口
|
||||
/// @param id 窗口ID
|
||||
/// @param type 窗口类型
|
||||
/// @param instance 窗口实例(所有权转移)
|
||||
/// @param parent 父窗口ID,默认为 INVALID_WINDOW_ID
|
||||
/// @return 成功返回true,失败返回false(如ID已存在)
|
||||
[[nodiscard]] auto register_window(window_id id, window_type type,
|
||||
mirage::window_ptr instance,
|
||||
window_id parent = INVALID_WINDOW_ID) -> bool;
|
||||
|
||||
/// 注销窗口
|
||||
/// @param id 窗口ID
|
||||
/// @return 成功返回true,失败返回false(如ID不存在)
|
||||
[[nodiscard]] auto unregister_window(window_id id) -> bool;
|
||||
|
||||
/// 检查窗口是否已注册
|
||||
/// @param id 窗口ID
|
||||
/// @return 如果已注册返回true,否则返回false
|
||||
[[nodiscard]] auto contains(window_id id) const -> bool;
|
||||
|
||||
// =========================================================================
|
||||
// 窗口查询
|
||||
// =========================================================================
|
||||
|
||||
/// 获取窗口实例
|
||||
/// @param id 窗口ID
|
||||
/// @return 窗口实例指针,如不存在返回nullptr
|
||||
[[nodiscard]] auto get_window(window_id id) -> mirage::window_interface*;
|
||||
|
||||
/// 获取窗口实例(const版本)
|
||||
/// @param id 窗口ID
|
||||
/// @return 窗口实例指针,如不存在返回nullptr
|
||||
[[nodiscard]] auto get_window(window_id id) const -> const mirage::window_interface*;
|
||||
|
||||
/// 获取窗口条目的完整信息
|
||||
/// @param id 窗口ID
|
||||
/// @return 窗口条目副本,如不存在返回nullopt
|
||||
[[nodiscard]] auto get_entry(window_id id) const -> std::optional<window_entry>;
|
||||
|
||||
/// 获取窗口类型
|
||||
/// @param id 窗口ID
|
||||
/// @return 窗口类型,如不存在返回nullopt
|
||||
[[nodiscard]] auto get_type(window_id id) const -> std::optional<window_type>;
|
||||
|
||||
// =========================================================================
|
||||
// 窗口关系管理
|
||||
// =========================================================================
|
||||
|
||||
/// 获取父窗口ID
|
||||
/// @param id 窗口ID
|
||||
/// @return 父窗口ID,如无父窗口或窗口不存在返回 INVALID_WINDOW_ID
|
||||
[[nodiscard]] auto get_parent(window_id id) const -> window_id;
|
||||
|
||||
/// 获取直接子窗口列表
|
||||
/// @param id 窗口ID
|
||||
/// @return 子窗口ID列表,如窗口不存在返回空列表
|
||||
[[nodiscard]] auto get_children(window_id id) const -> std::vector<window_id>;
|
||||
|
||||
/// 获取所有后代窗口(递归获取所有子窗口)
|
||||
/// @param id 窗口ID
|
||||
/// @return 所有后代窗口ID列表,如窗口不存在返回空列表
|
||||
[[nodiscard]] auto get_all_descendants(window_id id) const -> std::vector<window_id>;
|
||||
|
||||
/// 设置窗口的父窗口
|
||||
/// @param id 窗口ID
|
||||
/// @param new_parent 新的父窗口ID
|
||||
/// @return 成功返回true,失败返回false
|
||||
[[nodiscard]] auto set_parent(window_id id, window_id new_parent) -> bool;
|
||||
|
||||
/// 检查是否为祖先窗口
|
||||
/// @param ancestor 可能的祖先窗口ID
|
||||
/// @param descendant 可能的后代窗口ID
|
||||
/// @return 如果ancestor是descendant的祖先返回true
|
||||
[[nodiscard]] auto is_ancestor_of(window_id ancestor, window_id descendant) const -> bool;
|
||||
|
||||
// =========================================================================
|
||||
// 窗口状态管理
|
||||
// =========================================================================
|
||||
|
||||
/// 设置窗口状态
|
||||
/// @param id 窗口ID
|
||||
/// @param state 新状态
|
||||
/// @return 成功返回true,失败返回false(如窗口不存在)
|
||||
[[nodiscard]] auto set_state(window_id id, window_state state) -> bool;
|
||||
|
||||
/// 获取窗口状态
|
||||
/// @param id 窗口ID
|
||||
/// @return 窗口状态,如窗口不存在返回 HIDDEN
|
||||
[[nodiscard]] auto get_state(window_id id) const -> window_state;
|
||||
|
||||
// =========================================================================
|
||||
// 批量查询
|
||||
// =========================================================================
|
||||
|
||||
/// 按类型获取所有窗口ID
|
||||
/// @param type 窗口类型
|
||||
/// @return 该类型的所有窗口ID列表
|
||||
[[nodiscard]] auto get_windows_by_type(window_type type) const -> std::vector<window_id>;
|
||||
|
||||
/// 获取所有已注册的窗口ID
|
||||
/// @return 所有窗口ID列表
|
||||
[[nodiscard]] auto get_all_windows() const -> std::vector<window_id>;
|
||||
|
||||
/// 按状态获取所有窗口ID
|
||||
/// @param state 窗口状态
|
||||
/// @return 该状态的所有窗口ID列表
|
||||
[[nodiscard]] auto get_windows_by_state(window_state state) const -> std::vector<window_id>;
|
||||
|
||||
// =========================================================================
|
||||
// 统计信息
|
||||
// =========================================================================
|
||||
|
||||
/// 获取已注册窗口总数
|
||||
/// @return 窗口数量
|
||||
[[nodiscard]] auto count() const -> size_t;
|
||||
|
||||
/// 获取指定类型的窗口数量
|
||||
/// @param type 窗口类型
|
||||
/// @return 该类型的窗口数量
|
||||
[[nodiscard]] auto count_by_type(window_type type) const -> size_t;
|
||||
|
||||
/// 获取指定状态的窗口数量
|
||||
/// @param state 窗口状态
|
||||
/// @return 该状态的窗口数量
|
||||
[[nodiscard]] auto count_by_state(window_state state) const -> size_t;
|
||||
|
||||
/// 检查注册表是否为空
|
||||
/// @return 如果没有注册任何窗口返回true
|
||||
[[nodiscard]] auto empty() const -> bool;
|
||||
|
||||
// =========================================================================
|
||||
// 焦点和主窗口管理
|
||||
// =========================================================================
|
||||
|
||||
/// 获取当前焦点窗口ID
|
||||
/// @return 焦点窗口ID,如无焦点窗口返回 INVALID_WINDOW_ID
|
||||
[[nodiscard]] auto get_focused_window() const -> window_id;
|
||||
|
||||
/// 设置焦点窗口
|
||||
/// @param id 窗口ID
|
||||
/// @return 成功返回true,失败返回false(如窗口不存在)
|
||||
[[nodiscard]] auto set_focused_window(window_id id) -> bool;
|
||||
|
||||
/// 获取主窗口ID
|
||||
/// @return 主窗口ID,如无主窗口返回 INVALID_WINDOW_ID
|
||||
[[nodiscard]] auto get_main_window() const -> window_id;
|
||||
|
||||
/// 设置主窗口
|
||||
/// @param id 窗口ID
|
||||
/// @return 成功返回true,失败返回false(如窗口不存在)
|
||||
[[nodiscard]] auto set_main_window(window_id id) -> bool;
|
||||
|
||||
private:
|
||||
/// 读写互斥锁
|
||||
mutable std::shared_mutex mutex_;
|
||||
|
||||
/// 窗口存储映射表 (id -> entry)
|
||||
std::unordered_map<window_id, window_entry> windows_;
|
||||
|
||||
/// 当前焦点窗口ID
|
||||
window_id focused_window_{INVALID_WINDOW_ID};
|
||||
|
||||
/// 主窗口ID
|
||||
window_id main_window_{INVALID_WINDOW_ID};
|
||||
|
||||
// =========================================================================
|
||||
// 内部辅助方法
|
||||
// =========================================================================
|
||||
|
||||
/// 从父窗口的子窗口集合中移除指定窗口(不加锁)
|
||||
auto remove_from_parent_impl(window_id child_id, window_id parent_id) -> void;
|
||||
|
||||
/// 添加到父窗口的子窗口集合(不加锁)
|
||||
auto add_to_parent_impl(window_id child_id, window_id parent_id) -> void;
|
||||
|
||||
/// 递归收集所有后代窗口(不加锁)
|
||||
auto collect_descendants_impl(window_id id, std::vector<window_id>& result) const -> void;
|
||||
};
|
||||
|
||||
} // namespace mirage
|
||||
66
src/window/window_type.h
Normal file
66
src/window/window_type.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
|
||||
namespace mirage {
|
||||
|
||||
/// 窗口类型枚举
|
||||
enum class window_type : uint8_t {
|
||||
MAIN_WINDOW, ///< 主窗口
|
||||
CHILD_WINDOW, ///< 子窗口
|
||||
POPUP, ///< 弹出窗口
|
||||
DIALOG, ///< 对话框
|
||||
TOOLTIP ///< 提示窗口
|
||||
};
|
||||
|
||||
/// 窗口状态枚举
|
||||
enum class window_state : uint8_t {
|
||||
NORMAL, ///< 正常状态
|
||||
MINIMIZED, ///< 最小化
|
||||
MAXIMIZED, ///< 最大化
|
||||
FULLSCREEN, ///< 全屏
|
||||
HIDDEN ///< 隐藏
|
||||
};
|
||||
|
||||
/// 将窗口类型转换为字符串表示
|
||||
/// @param type 窗口类型
|
||||
/// @return 窗口类型的字符串表示
|
||||
[[nodiscard]] constexpr auto to_string(window_type type) noexcept -> std::string_view {
|
||||
switch (type) {
|
||||
case window_type::MAIN_WINDOW:
|
||||
return "MAIN_WINDOW";
|
||||
case window_type::CHILD_WINDOW:
|
||||
return "CHILD_WINDOW";
|
||||
case window_type::POPUP:
|
||||
return "POPUP";
|
||||
case window_type::DIALOG:
|
||||
return "DIALOG";
|
||||
case window_type::TOOLTIP:
|
||||
return "TOOLTIP";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
/// 将窗口状态转换为字符串表示
|
||||
/// @param state 窗口状态
|
||||
/// @return 窗口状态的字符串表示
|
||||
[[nodiscard]] constexpr auto to_string(window_state state) noexcept -> std::string_view {
|
||||
switch (state) {
|
||||
case window_state::NORMAL:
|
||||
return "NORMAL";
|
||||
case window_state::MINIMIZED:
|
||||
return "MINIMIZED";
|
||||
case window_state::MAXIMIZED:
|
||||
return "MAXIMIZED";
|
||||
case window_state::FULLSCREEN:
|
||||
return "FULLSCREEN";
|
||||
case window_state::HIDDEN:
|
||||
return "HIDDEN";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mirage
|
||||
Reference in New Issue
Block a user