diff options
| author | Yuqian Yang <crupest@crupest.life> | 2025-11-17 13:52:52 +0800 |
|---|---|---|
| committer | Yuqian Yang <crupest@crupest.life> | 2025-11-17 13:52:52 +0800 |
| commit | f7c4d19df66c602d74795e98ce2ee4390d06fbb4 (patch) | |
| tree | 5d91dc18ae8129652d4c5b88234d0bb7b93dcf13 /include | |
| parent | c9f31440d65a867e2316e9a19ee3f5db2d0e53a7 (diff) | |
| download | cru-f7c4d19df66c602d74795e98ce2ee4390d06fbb4.tar.gz cru-f7c4d19df66c602d74795e98ce2ee4390d06fbb4.tar.bz2 cru-f7c4d19df66c602d74795e98ce2ee4390d06fbb4.zip | |
Harden delete after free.
Diffstat (limited to 'include')
| -rw-r--r-- | include/cru/ui/controls/Control.h | 13 | ||||
| -rw-r--r-- | include/cru/ui/controls/Window.h | 33 |
2 files changed, 35 insertions, 11 deletions
diff --git a/include/cru/ui/controls/Control.h b/include/cru/ui/controls/Control.h index 684bc960..94de4cdc 100644 --- a/include/cru/ui/controls/Control.h +++ b/include/cru/ui/controls/Control.h @@ -1,12 +1,14 @@ #pragma once #include "../Base.h" #include "../DeleteLater.h" +#include "../events/KeyEventArgs.h" +#include "../events/MouseWheelEventArgs.h" #include "../events/UiEvents.h" +#include "../render/MeasureRequirement.h" #include "../render/RenderObject.h" #include "../style/StyleRuleSet.h" -#include "cru/ui/events/KeyEventArgs.h" -#include "cru/ui/events/MouseWheelEventArgs.h" -#include "cru/ui/render/MeasureRequirement.h" + +#include <cru/base/SelfResolvable.h> namespace cru::ui::controls { @@ -19,7 +21,9 @@ namespace cru::ui::controls { * - RemoveChild(Control* child) * The last two methods are totally for convenient control tree management. */ -class CRU_UI_API Control : public Object, public DeleteLaterImpl { +class CRU_UI_API Control : public Object, + public DeleteLaterImpl, + public SelfResolvable<Control> { friend class RootControl; CRU_DEFINE_CLASS_LOG_TAG("Control") @@ -41,6 +45,7 @@ class CRU_UI_API Control : public Object, public DeleteLaterImpl { Control* GetParent() const { return parent_; } void SetParent(Control* parent); + bool HasAncestor(Control* control); virtual void ForEachChild(const std::function<void(Control*)>& predicate) = 0; diff --git a/include/cru/ui/controls/Window.h b/include/cru/ui/controls/Window.h index e25694ba..88320219 100644 --- a/include/cru/ui/controls/Window.h +++ b/include/cru/ui/controls/Window.h @@ -13,6 +13,8 @@ namespace cru::ui::controls { class CRU_UI_API Window : public LayoutControl<render::StackLayoutRenderObject> { CRU_DEFINE_CLASS_LOG_TAG("cru::ui::controls::Window") + friend Control; + public: static constexpr std::string_view kControlType = "Window"; @@ -58,7 +60,6 @@ class CRU_UI_API Window void SetOverrideCursor(std::shared_ptr<platform::gui::ICursor> cursor); bool IsInEventHandling(); - void UpdateCursor(); CRU_DEFINE_EVENT(AfterLayout, std::nullptr_t) @@ -104,7 +105,8 @@ class CRU_UI_API Window if (original_sender == nullptr || original_sender == last_receiver) return; std::string log = "Begin dispatching routed event " + - (original_sender->*event_ptr)()->GetName() + ":\n\tTunnel:"; + (original_sender->*event_ptr)()->GetName() + + ":\n\tTunnel:"; Guard logging_guard([&] { log += "\nEnd dispatching routed event " + @@ -112,11 +114,11 @@ class CRU_UI_API Window CRU_LOG_TAG_DEBUG("{}", log); }); - std::vector<Control*> receive_list; + std::vector<ObjectResolver<Control>> receive_list; auto parent = original_sender; while (parent != last_receiver) { - receive_list.push_back(parent); + receive_list.push_back(parent->CreateResolver()); parent = parent->GetParent(); } @@ -124,8 +126,12 @@ class CRU_UI_API Window // tunnel for (auto i = receive_list.crbegin(); i != receive_list.crend(); ++i) { - auto control = *i; + auto control = i->Resolve(); log += " "; + if (!control) { + log += "(deleted)"; + continue; + } log += control->GetDebugId(); EventArgs event_args(control, original_sender, std::forward<Args>(args)...); @@ -140,8 +146,13 @@ class CRU_UI_API Window // bubble if (!handled) { log += "\n\tBubble:"; - for (auto control : receive_list) { + for (auto resolver : receive_list) { + auto control = resolver.Resolve(); log += " "; + if (!control) { + log += "(deleted)"; + continue; + } log += control->GetDebugId(); EventArgs event_args(control, original_sender, std::forward<Args>(args)...); @@ -155,8 +166,13 @@ class CRU_UI_API Window log += "\n\tDirect:"; // direct - for (auto control : receive_list) { + for (auto resolver : receive_list) { + auto control = resolver.Resolve(); log += " "; + if (!control) { + log += "(deleted)"; + continue; + } log += control->GetDebugId(); EventArgs event_args(control, original_sender, std::forward<Args>(args)...); @@ -164,6 +180,9 @@ class CRU_UI_API Window } } + void UpdateCursor(); + void NotifyControlDestroyed(Control* control); + private: int event_handling_count_; |
