修复控件树重建,修复hover状态不正确

This commit is contained in:
Nanako 2025-03-24 01:43:01 +08:00
parent d650fcb558
commit 17c14a7a14
10 changed files with 51 additions and 21 deletions

View File

@ -14,7 +14,7 @@ if (MSVC)
endif ()
if (WIN32)
# Windows
add_definitions(-DWIN32_LEAN_AND_MEAN)
# add_definitions(-DWIN32_LEAN_AND_MEAN)
add_definitions(-DUNICODE -D_UNICODE)
endif ()

View File

@ -16,18 +16,17 @@ int main(int argc, char* argv[]) {
window->show();
mirage_app::get_render_context()->setup_surface(window.get());
widget_manager::get().init_window(window);
auto weak_border = widget_manager::get().new_widget<mborder>(window.get());
auto border = weak_border.lock();
auto button = widget_manager::get().new_widget<mbutton>(window.get());
border->set_content(button.lock())
.margin({5});
auto border = weak_border.lock();
border->set_content(button.lock()).margin({ 5 });
window->set_content(border);
app.run();
return 0;
}

View File

@ -294,7 +294,7 @@ void render_elements::create_resources() {
}
void render_elements::load_mirage_pipelines() {
#ifdef MIRAGE_USE_HDR
#if MIRAGE_USE_HDR
auto format = MIRAGE_HDR_FORMAT;
#else
auto format = MIRAGE_PIXEL_FORMAT;

View File

@ -37,7 +37,7 @@ void mwindow::on_resize(int width, int height) {
if (content_widget_) {
content_widget_->set_geometry(new_geometry);
}
invalidate(invalidate_reason::all);
invalidate_all();
}
void mwindow::rebuild_swapchain() {
@ -52,6 +52,26 @@ void mwindow::on_paint(mirage_paint_context& in_context) {
content_widget_->on_paint(in_context);
}
void invalidate_recursive(const std::shared_ptr<mwidget>& in_widget, invalidate_reason in_reason) {
in_widget->invalidate(in_reason);
for (const auto& child : in_widget->get_children()) {
const auto& ptr = widget_manager::get().get_component_ref<widget_ptr>(child);
invalidate_recursive(ptr, in_reason);
}
// 如果是布局失效, 重置期望大小
if (has_any_flag(in_reason, invalidate_reason::layout)) {
if (auto* layout = in_widget->get_component<widget_layout>()) {
layout->desired_size.reset();
}
}
}
void mwindow::invalidate_all() {
// 设置失效标记
invalidate_recursive(shared_from_this(), invalidate_reason::all);
}
void mwindow::handle_mouse_move(const Eigen::Vector2f& in_window_pos) {
on_mouse_move_delegate.broadcast(in_window_pos);
}

View File

@ -394,6 +394,8 @@ public:
*/
virtual void on_paint(mirage_paint_context& in_context) override;
void invalidate_all();
multicast_delegate<const Eigen::Vector2i&> on_resize_delegate;
multicast_delegate<mwindow*> on_close_delegate;

View File

@ -9,7 +9,8 @@
#define WINDOW_HANDLE static_cast<HWND>(window_handle_)
std::vector<mwindow*> windows;
mwindow* get_window_from_hwnd(const HWND hwnd) {
bool mouse_tracking_ = FALSE;
mwindow* get_window_from_hwnd(const HWND hwnd) {
for (const auto& window: windows) {
if (window->get_window_handle() == hwnd) {
return window;
@ -56,6 +57,15 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
const Eigen::Vector2f pos(static_cast<float>(x), static_cast<float>(y));
window->handle_mouse_move(pos);
}
if (!mouse_tracking_) {
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hwnd;
tme.dwHoverTime = HOVER_DEFAULT;
TrackMouseEvent(&tme);
mouse_tracking_ = TRUE;
}
processed = true;
}
if (uMsg >= WM_LBUTTONDOWN && uMsg <= WM_MBUTTONDBLCLK) {
@ -73,6 +83,7 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
processed = true;
}
if (uMsg == WM_MOUSELEAVE) {
mouse_tracking_ = FALSE;
if (const auto window = get_window_from_hwnd(hwnd)) {
window->handle_mouse_leave();
}

View File

@ -83,7 +83,7 @@ void mbutton::on_mouse_leave() {
hit_test_handle mbutton::on_mouse_move(const Eigen::Vector2f& in_position) {
mborder::on_mouse_move(in_position);
std::cout << this << ": Mouse moved!" << in_position.x() << ", " << in_position.y() << std::endl;
// std::cout << this << ": Mouse moved!" << in_position.x() << ", " << in_position.y() << std::endl;
color_ = {1, 1, 0, 1};
return hit_test_handle::handled();
}

View File

@ -58,9 +58,7 @@ void mwidget::set_parent(const widget_key& in_parent) {
parent_hierarchy->add_child(key_);
// 4. 通知父节点需要重新计算布局
if (const auto parent = get_parent_widget().lock()) {
parent->invalidate(invalidate_reason::layout);
}
invalidate(invalidate_reason::layout);
}
void mwidget::invalidate(invalidate_reason in_reason) {
@ -75,7 +73,7 @@ void mwidget::invalidate(invalidate_reason in_reason) {
}
// 如果是布局失效, 重置期望大小
if (in_reason == invalidate_reason::layout) {
if (has_any_flag(in_reason, invalidate_reason::layout)) {
if (auto* layout = get_component<widget_layout>()) {
layout->desired_size.reset();
}

View File

@ -27,7 +27,7 @@ struct widget_key {
}
operator bool() const { return window_ && !entity_.isNull(); }
operator mustache::Entity() const { return entity_; }
operator const mustache::Entity&() const { return entity_; }
operator mwindow*() const { return window_; }
bool operator==(const widget_key& in_other) const { return window_ == in_other.window_ && entity_ == in_other.entity_; }
@ -35,8 +35,8 @@ struct widget_key {
static auto invalid() { return widget_key(nullptr, mustache::Entity()); }
[[nodiscard]] auto get_window() const { return window_; }
[[nodiscard]] auto get_entity() const { return entity_; }
[[nodiscard]] const auto& get_window() const { return window_; }
[[nodiscard]] const auto& get_entity() const { return entity_; }
private:
mwindow* window_;
mustache::Entity entity_;
@ -80,11 +80,11 @@ struct widget_visibility {
void set_enabled(const bool in_enabled) { enabled = in_enabled; }
void set_visibility(const visibility_t in_visibility) { visibility = in_visibility; }
bool can_hit_test() const;
[[nodiscard]] bool can_hit_test() const;
};
struct widget_invalidate {
invalidate_reason invalidate;
invalidate_reason invalidate = invalidate_reason::none;
void set(const invalidate_reason in_reason) { set_flag(invalidate, in_reason); }
void unset(const invalidate_reason in_reason) { clear_flag(invalidate, in_reason); }

View File

@ -64,8 +64,8 @@ void widget_hit_test_system::process_mouse_move(const Eigen::Vector2f& in_window
if (auto ptr = widget_manager::get().get_component<widget_ptr>(last_hover_widget_))
ptr->widget->on_mouse_leave();
last_hit_widget_ = result;
if (auto ptr = widget_manager::get().get_component<widget_ptr>(last_hit_widget_))
last_hover_widget_ = result;
if (auto ptr = widget_manager::get().get_component<widget_ptr>(last_hover_widget_))
ptr->widget->on_mouse_enter();
}