aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-03-29 12:24:06 +0800
committercrupest <crupest@outlook.com>2022-03-29 12:24:06 +0800
commit7a564d98db0b7c7be5b3bfac955cb88998a472ac (patch)
tree891abaf06a4e011a798c8daf5f063230ec67f995 /src
parent91695b78f565239223fc6f3a10b0219b8dc1b6f8 (diff)
downloadcru-7a564d98db0b7c7be5b3bfac955cb88998a472ac.tar.gz
cru-7a564d98db0b7c7be5b3bfac955cb88998a472ac.tar.bz2
cru-7a564d98db0b7c7be5b3bfac955cb88998a472ac.zip
...
Diffstat (limited to 'src')
-rw-r--r--src/ui/DeleteLater.cpp2
-rw-r--r--src/ui/components/Component.cpp6
-rw-r--r--src/ui/controls/Control.cpp15
-rw-r--r--src/ui/controls/TextHostControlService.cpp21
-rw-r--r--src/ui/host/RoutedEventDispatch.h9
-rw-r--r--src/ui/host/WindowHost.cpp22
6 files changed, 55 insertions, 20 deletions
diff --git a/src/ui/DeleteLater.cpp b/src/ui/DeleteLater.cpp
index 8a40642f..f8911ae1 100644
--- a/src/ui/DeleteLater.cpp
+++ b/src/ui/DeleteLater.cpp
@@ -9,4 +9,6 @@ DeleteLaterImpl::~DeleteLaterImpl() {}
void DeleteLaterImpl::DeleteLater() {
GetUiApplication()->SetImmediate([this] { delete this; });
}
+
+void DeleteLaterImpl::OnPrepareDelete() {}
} // namespace cru::ui
diff --git a/src/ui/components/Component.cpp b/src/ui/components/Component.cpp
index ddf65515..01db8710 100644
--- a/src/ui/components/Component.cpp
+++ b/src/ui/components/Component.cpp
@@ -1,5 +1,7 @@
#include "cru/ui/components/Component.h"
+#include "cru/ui/controls/Control.h"
+
namespace cru::ui::components {
-
-}
+void Component::OnPrepareDelete() { GetRootControl()->RemoveFromParent(); }
+} // namespace cru::ui::components
diff --git a/src/ui/controls/Control.cpp b/src/ui/controls/Control.cpp
index f2d4760e..3b0d4be3 100644
--- a/src/ui/controls/Control.cpp
+++ b/src/ui/controls/Control.cpp
@@ -1,5 +1,6 @@
#include "cru/ui/controls/Control.h"
+#include "cru/common/log/Logger.h"
#include "cru/platform/gui/Cursor.h"
#include "cru/platform/gui/UiApplication.h"
#include "cru/ui/host/WindowHost.h"
@@ -28,6 +29,11 @@ Control::Control() {
}
Control::~Control() {
+ if (host::WindowHost::IsInEventHandling()) {
+ CRU_LOG_ERROR(
+ u"Control destroyed during event handling. Please use DeleteLater.");
+ }
+
in_destruction_ = true;
RemoveFromParent();
}
@@ -120,12 +126,7 @@ void Control::OnParentChangedCore(Control* old_parent, Control* new_parent) {
void Control::OnWindowHostChangedCore(host::WindowHost* old_host,
host::WindowHost* new_host) {
if (old_host != nullptr) {
- if (old_host->GetMouseCaptureControl() == this) {
- old_host->CaptureMouseFor(nullptr);
- }
- if (old_host->GetMouseHoverControl() == this) {
- old_host->mouse_hover_control_ = nullptr;
- }
+ old_host->OnControlDetach(this);
}
if (!in_destruction_) {
@@ -136,4 +137,6 @@ void Control::OnWindowHostChangedCore(host::WindowHost* old_host,
OnWindowHostChanged(old_host, new_host);
}
}
+
+void Control::OnPrepareDelete() { RemoveFromParent(); }
} // namespace cru::ui::controls
diff --git a/src/ui/controls/TextHostControlService.cpp b/src/ui/controls/TextHostControlService.cpp
index 15d9102c..d6c40a36 100644
--- a/src/ui/controls/TextHostControlService.cpp
+++ b/src/ui/controls/TextHostControlService.cpp
@@ -2,9 +2,9 @@
#include "../Helper.h"
#include "cru/common/Base.h"
-#include "cru/common/log/Logger.h"
#include "cru/common/String.h"
#include "cru/common/StringUtil.h"
+#include "cru/common/log/Logger.h"
#include "cru/platform/graphics/Font.h"
#include "cru/platform/gui/Base.h"
#include "cru/platform/gui/Clipboard.h"
@@ -15,6 +15,7 @@
#include "cru/platform/gui/Window.h"
#include "cru/ui/Base.h"
#include "cru/ui/DebugFlags.h"
+#include "cru/ui/DeleteLater.h"
#include "cru/ui/components/Menu.h"
#include "cru/ui/events/UiEvents.h"
#include "cru/ui/helper/ShortcutHub.h"
@@ -149,7 +150,7 @@ std::vector<TextControlMovePattern> TextControlMovePattern::kDefaultPatterns = {
TextHostControlService::TextHostControlService(gsl::not_null<Control*> control)
: control_(control),
text_host_control_(dynamic_cast<ITextHostControl*>(control.get())) {
- context_menu_ = std::make_unique<components::PopupMenu>();
+ context_menu_ = MakeDeleteLaterPtr<components::PopupMenu>();
SetUpShortcuts();
@@ -335,11 +336,12 @@ void TextHostControlService::SetCaretBlinkDuration(int milliseconds) {
void TextHostControlService::ScrollToCaret() {
if (const auto scroll_render_object = this->GetScrollRenderObject()) {
- this->control_->GetWindowHost()->RunAfterLayoutStable(
- [this, scroll_render_object]() {
- const auto caret_rect = this->GetTextRenderObject()->GetCaretRect();
- scroll_render_object->ScrollToContain(caret_rect, Thickness{5.f});
- });
+ auto window_host = this->control_->GetWindowHost();
+ if (window_host)
+ window_host->RunAfterLayoutStable([this, scroll_render_object]() {
+ const auto caret_rect = this->GetTextRenderObject()->GetCaretRect();
+ scroll_render_object->ScrollToContain(caret_rect, Thickness{5.f});
+ });
}
}
@@ -465,8 +467,7 @@ void TextHostControlService::UpdateInputMethodPosition() {
right_bottom.y += 5;
if constexpr (debug_flags::text_service) {
- CRU_LOG_DEBUG(
- u"Calculate input method candidate window position: {}.",
+ CRU_LOG_DEBUG(u"Calculate input method candidate window position: {}.",
right_bottom);
}
@@ -693,7 +694,7 @@ void TextHostControlService::SetUpShortcuts() {
void TextHostControlService::OpenContextMenu(const Point& position,
ContextMenuItem items) {
- context_menu_ = std::make_unique<components::PopupMenu>();
+ context_menu_ = MakeDeleteLaterPtr<components::PopupMenu>();
auto menu = context_menu_->GetMenu();
if (items & ContextMenuItem::kSelectAll) {
menu->AddTextItem(u"Select All", [this] { this->SelectAll(); });
diff --git a/src/ui/host/RoutedEventDispatch.h b/src/ui/host/RoutedEventDispatch.h
index 2f437b31..5d1c8ce5 100644
--- a/src/ui/host/RoutedEventDispatch.h
+++ b/src/ui/host/RoutedEventDispatch.h
@@ -3,10 +3,11 @@
#include "cru/common/log/Logger.h"
#include "cru/ui/DebugFlags.h"
#include "cru/ui/controls/Control.h"
+#include "cru/ui/host/WindowHost.h"
#include <vector>
-namespace cru::ui {
+namespace cru::ui::host {
// Dispatch the event.
//
// This will raise routed event of the control and its parent and parent's
@@ -40,6 +41,8 @@ void DispatchEvent(
return;
}
+ WindowHost::EnterEventHandling();
+
std::vector<ObjectResolver<controls::Control>> receive_list;
auto parent = original_sender;
@@ -119,5 +122,7 @@ void DispatchEvent(
if constexpr (debug_flags::routed_event)
CRU_LOG_DEBUG(u"Routed event dispatch finished.");
+
+ WindowHost::LeaveEventHandling();
}
-} // namespace cru::ui
+} // namespace cru::ui::host
diff --git a/src/ui/host/WindowHost.cpp b/src/ui/host/WindowHost.cpp
index f4a9a928..737a7594 100644
--- a/src/ui/host/WindowHost.cpp
+++ b/src/ui/host/WindowHost.cpp
@@ -7,6 +7,7 @@
#include "cru/platform/gui/InputMethod.h"
#include "cru/platform/gui/UiApplication.h"
#include "cru/platform/gui/Window.h"
+#include "cru/ui/Base.h"
#include "cru/ui/DebugFlags.h"
#include "cru/ui/host/LayoutPaintCycler.h"
#include "cru/ui/render/MeasureRequirement.h"
@@ -105,6 +106,15 @@ inline void BindNativeEvent(
}
} // namespace
+int WindowHost::event_handling_depth_ = 0;
+
+void WindowHost::EnterEventHandling() { event_handling_depth_++; }
+
+void WindowHost::LeaveEventHandling() {
+ Expects(event_handling_depth_ > 0);
+ event_handling_depth_--;
+}
+
WindowHost::WindowHost(controls::Control* root_control)
: root_control_(root_control), focus_control_(root_control) {
root_render_object_ = root_control->GetRenderObject();
@@ -438,4 +448,16 @@ void WindowHost::SetOverrideCursor(
override_cursor_ = cursor;
UpdateCursor();
}
+
+void WindowHost::OnControlDetach(controls::Control* control) {
+ if (GetFocusControl() == control) {
+ SetFocusControl(nullptr);
+ }
+ if (GetMouseCaptureControl() == control) {
+ CaptureMouseFor(nullptr);
+ }
+ if (GetMouseHoverControl() == control) {
+ mouse_hover_control_ = HitTest(GetNativeWindow()->GetMousePosition());
+ }
+}
} // namespace cru::ui::host