aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--demos/input_method/main.cpp7
-rw-r--r--demos/main/main.cpp6
-rw-r--r--include/cru/ui/ContentControl.hpp13
-rw-r--r--include/cru/ui/Control.hpp29
-rw-r--r--include/cru/ui/LayoutControl.hpp18
-rw-r--r--include/cru/ui/NoChildControl.hpp10
-rw-r--r--include/cru/ui/Window.hpp18
-rw-r--r--include/cru/ui/WindowHost.hpp72
-rw-r--r--include/cru/ui/render/Base.hpp1
-rw-r--r--include/cru/ui/render/RenderObject.hpp20
-rw-r--r--include/cru/ui/render/WindowRenderObject.hpp34
-rw-r--r--src/ui/CMakeLists.txt2
-rw-r--r--src/ui/ContentControl.cpp24
-rw-r--r--src/ui/Control.cpp106
-rw-r--r--src/ui/LayoutControl.cpp47
-rw-r--r--src/ui/NoChildControl.cpp4
-rw-r--r--src/ui/Window.cpp31
-rw-r--r--src/ui/WindowHost.cpp98
-rw-r--r--src/ui/controls/TextControlService.hpp77
-rw-r--r--src/ui/render/RenderObject.cpp25
-rw-r--r--src/ui/render/WindowRenderObject.cpp44
-rw-r--r--src/win/native/UiApplication.cpp5
-rw-r--r--src/win/native/Window.cpp1
23 files changed, 271 insertions, 421 deletions
diff --git a/demos/input_method/main.cpp b/demos/input_method/main.cpp
index bff0e1d3..06098253 100644
--- a/demos/input_method/main.cpp
+++ b/demos/input_method/main.cpp
@@ -14,12 +14,9 @@ int main() {
auto graph_factory = application->GetGraphFactory();
- auto window_resolver = application->CreateWindow(nullptr);
+ auto window = application->CreateWindow(nullptr);
- auto window = window_resolver->Resolve();
-
- auto input_method_context =
- application->GetInputMethodManager()->GetContext(window);
+ auto input_method_context = window->GetInputMethodContext();
auto brush = graph_factory->CreateSolidColorBrush();
brush->SetColor(colors::black);
diff --git a/demos/main/main.cpp b/demos/main/main.cpp
index f7635231..e973682e 100644
--- a/demos/main/main.cpp
+++ b/demos/main/main.cpp
@@ -2,8 +2,8 @@
#include "cru/platform/native/UiApplication.hpp"
#include "cru/platform/native/Window.hpp"
#include "cru/ui/Base.hpp"
-#include "cru/ui/WindowHost.hpp"
#include "cru/ui/Window.hpp"
+#include "cru/ui/WindowHost.hpp"
#include "cru/ui/controls/Button.hpp"
#include "cru/ui/controls/FlexLayout.hpp"
#include "cru/ui/controls/TextBlock.hpp"
@@ -30,7 +30,7 @@ int main() {
flex_layout->SetContentMainAlign(cru::ui::FlexCrossAlignment::Center);
flex_layout->SetItemCrossAlign(cru::ui::FlexCrossAlignment::Center);
- window->SetChild(flex_layout);
+ window->AddChild(flex_layout, 0);
const auto text_block = TextBlock::Create();
text_block->SetText(u"Hello World from CruUI!");
@@ -45,7 +45,7 @@ int main() {
const auto text_box = TextBox::Create();
flex_layout->AddChild(text_box, 2);
- window->GetWindowHost()->GetNativeWindowResolver()->Resolve()->SetVisible(true);
+ window->GetWindowHost()->GetNativeWindow()->SetVisible(true);
return application->Run();
}
diff --git a/include/cru/ui/ContentControl.hpp b/include/cru/ui/ContentControl.hpp
index 19f13a1d..ba5b6b2f 100644
--- a/include/cru/ui/ContentControl.hpp
+++ b/include/cru/ui/ContentControl.hpp
@@ -4,26 +4,23 @@
namespace cru::ui {
class ContentControl : public Control {
protected:
- ContentControl();
+ ContentControl() = default;
public:
ContentControl(const ContentControl& other) = delete;
ContentControl(ContentControl&& other) = delete;
ContentControl& operator=(const ContentControl& other) = delete;
ContentControl& operator=(ContentControl&& other) = delete;
- ~ContentControl() override;
+ ~ContentControl() override = default;
- const std::vector<Control*>& GetChildren() const override final {
- return child_vector_;
- }
- Control* GetChild() const { return child_; }
+ Control* GetChild() const;
void SetChild(Control* child);
protected:
virtual void OnChildChanged(Control* old_child, Control* new_child);
private:
- std::vector<Control*> child_vector_;
- Control*& child_;
+ using Control::AddChild;
+ using Control::RemoveChild;
};
} // namespace cru::ui
diff --git a/include/cru/ui/Control.hpp b/include/cru/ui/Control.hpp
index 692dcc9b..0021ad62 100644
--- a/include/cru/ui/Control.hpp
+++ b/include/cru/ui/Control.hpp
@@ -1,9 +1,9 @@
#pragma once
#include "Base.hpp"
+#include "UiEvent.hpp"
#include "cru/common/Event.hpp"
#include "render/Base.hpp"
-#include "UiEvent.hpp"
#include <string_view>
@@ -19,39 +19,31 @@ class Control : public Object {
Control(Control&& other) = delete;
Control& operator=(const Control& other) = delete;
Control& operator=(Control&& other) = delete;
- ~Control() override = default;
+ ~Control() override;
public:
virtual std::u16string_view GetControlType() const = 0;
//*************** region: tree ***************
public:
- // Get the ui host if attached, otherwise, return nullptr.
- WindowHost* GetWindowHost() const { return ui_host_; }
+ WindowHost* GetWindowHost() const;
Control* GetParent() const { return parent_; }
- virtual const std::vector<Control*>& GetChildren() const = 0;
+ const std::vector<Control*>& GetChildren() const { return children_; }
// Traverse the tree rooted the control including itself.
void TraverseDescendants(const std::function<void(Control*)>& predicate);
- void _SetParent(Control* parent);
- void _SetDescendantWindowHost(WindowHost* host);
-
- private:
- static void _TraverseDescendants(
- Control* control, const std::function<void(Control*)>& predicate);
-
public:
virtual render::RenderObject* GetRenderObject() const = 0;
//*************** region: focus ***************
public:
- bool RequestFocus();
-
bool HasFocus();
+ void SetFocus();
+
//*************** region: mouse ***************
public:
bool IsMouseOver() const { return is_mouse_over_; }
@@ -134,15 +126,22 @@ class Control : public Object {
//*************** region: tree ***************
protected:
+ void AddChild(Control* control, Index position);
+ void RemoveChild(Index position);
+ virtual void OnAddChild(Control* child, Index position);
+ virtual void OnRemoveChild(Control* child, Index position);
virtual void OnParentChanged(Control* old_parent, Control* new_parent);
virtual void OnAttachToHost(WindowHost* host);
virtual void OnDetachFromHost(WindowHost* host);
+ protected:
virtual void OnMouseHoverChange(bool newHover) { CRU_UNUSED(newHover) }
private:
- WindowHost* ui_host_ = nullptr;
Control* parent_ = nullptr;
+ std::vector<Control*> children_;
+
+ WindowHost* window_host_ = nullptr;
private:
bool is_mouse_over_ = false;
diff --git a/include/cru/ui/LayoutControl.hpp b/include/cru/ui/LayoutControl.hpp
index 7997b37e..69d5cd0b 100644
--- a/include/cru/ui/LayoutControl.hpp
+++ b/include/cru/ui/LayoutControl.hpp
@@ -11,21 +11,9 @@ class LayoutControl : public Control {
LayoutControl(LayoutControl&& other) = delete;
LayoutControl& operator=(const LayoutControl& other) = delete;
LayoutControl& operator=(LayoutControl&& other) = delete;
- ~LayoutControl() override;
+ ~LayoutControl() override = default;
- const std::vector<Control*>& GetChildren() const override final {
- return children_;
- }
-
- void AddChild(Control* control, Index position);
-
- void RemoveChild(Index position);
-
- protected:
- virtual void OnAddChild(Control* child, Index position);
- virtual void OnRemoveChild(Control* child, Index position);
-
- private:
- std::vector<Control*> children_;
+ using Control::AddChild;
+ using Control::RemoveChild;
};
} // namespace cru::ui
diff --git a/include/cru/ui/NoChildControl.hpp b/include/cru/ui/NoChildControl.hpp
index 1a31ae7e..0d8a8e34 100644
--- a/include/cru/ui/NoChildControl.hpp
+++ b/include/cru/ui/NoChildControl.hpp
@@ -3,9 +3,6 @@
namespace cru::ui {
class NoChildControl : public Control {
- private:
- static const std::vector<Control*> empty_control_vector;
-
protected:
NoChildControl() = default;
@@ -16,9 +13,8 @@ class NoChildControl : public Control {
NoChildControl& operator=(NoChildControl&& other) = delete;
~NoChildControl() override = default;
- protected:
- const std::vector<Control*>& GetChildren() const override final {
- return empty_control_vector;
- }
+ private:
+ using Control::AddChild;
+ using Control::RemoveChild;
};
} // namespace cru::ui
diff --git a/include/cru/ui/Window.hpp b/include/cru/ui/Window.hpp
index 5ea24855..0739e3dc 100644
--- a/include/cru/ui/Window.hpp
+++ b/include/cru/ui/Window.hpp
@@ -1,10 +1,8 @@
#pragma once
-#include "ContentControl.hpp"
+#include "LayoutControl.hpp"
namespace cru::ui {
-class Window final : public ContentControl {
- friend WindowHost;
-
+class Window final : public LayoutControl {
public:
static constexpr std::u16string_view control_type = u"Window";
@@ -12,9 +10,7 @@ class Window final : public ContentControl {
static Window* CreateOverlapped();
private:
- struct tag_overlapped_constructor {};
-
- explicit Window(tag_overlapped_constructor);
+ Window();
public:
Window(const Window& other) = delete;
@@ -29,12 +25,12 @@ class Window final : public ContentControl {
render::RenderObject* GetRenderObject() const override;
protected:
- void OnChildChanged(Control* old_child, Control* new_child) override;
+ void OnAddChild(Control* child, Index position) override;
+ void OnRemoveChild(Control* child, Index position) override;
private:
- std::unique_ptr<WindowHost> managed_ui_host_;
+ std::unique_ptr<WindowHost> window_host_;
- // WindowHost is responsible to take care of lifetime of this.
- render::WindowRenderObject* render_object_;
+ std::unique_ptr<render::StackLayoutRenderObject> render_object_;
};
} // namespace cru::ui
diff --git a/include/cru/ui/WindowHost.hpp b/include/cru/ui/WindowHost.hpp
index 83ef2f64..8efb505d 100644
--- a/include/cru/ui/WindowHost.hpp
+++ b/include/cru/ui/WindowHost.hpp
@@ -1,20 +1,22 @@
#pragma once
-#include <functional>
#include "Base.hpp"
#include "cru/common/Event.hpp"
-#include "cru/common/SelfResolvable.hpp"
+#include "cru/platform/native/UiApplication.hpp"
+#include "cru/platform/native/Window.hpp"
#include "render/Base.hpp"
+#include <functional>
+
namespace cru::ui {
struct AfterLayoutEventArgs {};
-class WindowHost : public Object, public SelfResolvable<WindowHost> {
+
+// The bridge between control tree and native window.
+class WindowHost : public Object {
CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::WindowHost")
public:
- // This will create root window render object and attach it to window.
- // It will also create and manage a native window.
- WindowHost(Window* window);
+ WindowHost(Control* root_control);
CRU_DELETE_COPY(WindowHost)
CRU_DELETE_MOVE(WindowHost)
@@ -22,6 +24,8 @@ class WindowHost : public Object, public SelfResolvable<WindowHost> {
~WindowHost() override;
public:
+ platform::native::INativeWindow* GetNativeWindow() { return native_window_; }
+
// Mark the layout as invalid, and arrange a re-layout later.
// This method could be called more than one times in a message cycle. But
// layout only takes place once.
@@ -36,13 +40,18 @@ class WindowHost : public Object, public SelfResolvable<WindowHost> {
return &after_layout_event_;
}
+ void Relayout();
+ void Relayout(const Size& available_size);
+
+ // Is layout is invalid, wait for relayout and then run the action. Otherwist
+ // run it right now.
+ void RunAfterLayoutStable(std::function<void()> action);
+
// If true, preferred size of root render object is set to window size when
// measure. Default is true.
bool IsLayoutPreferToFillWindow() const;
void SetLayoutPreferToFillWindow(bool value);
- void Relayout();
-
// Get current control that mouse hovers on. This ignores the mouse-capture
// control. Even when mouse is captured by another control, this function
// return the control under cursor. You can use `GetMouseCaptureControl` to
@@ -51,12 +60,10 @@ class WindowHost : public Object, public SelfResolvable<WindowHost> {
//*************** region: focus ***************
- // Request focus for specified control.
- bool RequestFocusFor(Control* control);
-
- // Get the control that has focus.
Control* GetFocusControl();
+ void SetFocusControl(Control* control);
+
//*************** region: focus ***************
// Pass nullptr to release capture. If mouse is already capture by a control,
@@ -78,19 +85,6 @@ class WindowHost : public Object, public SelfResolvable<WindowHost> {
void UpdateCursor();
- std::shared_ptr<platform::native::INativeWindowResolver>
- GetNativeWindowResolver() {
- return native_window_resolver_;
- }
-
- bool IsRetainAfterDestroy() { return retain_after_destroy_; }
-
- void SetRetainAfterDestroy(bool destroy) { retain_after_destroy_ = destroy; }
-
- // Is layout is invalid, wait for relayout and then run the action. Otherwist
- // run it right now.
- void RunAfterLayoutStable(std::function<void()> action);
-
private:
//*************** region: native messages ***************
void OnNativeDestroy(platform::native::INativeWindow* window, std::nullptr_t);
@@ -126,33 +120,21 @@ class WindowHost : public Object, public SelfResolvable<WindowHost> {
bool no_enter);
private:
- bool need_layout_ = false;
+ Control* root_control_;
+ render::RenderObject* root_render_object_;
+
+ platform::native::INativeWindow* native_window_;
+ bool need_layout_ = false;
+ platform::native::TimerAutoCanceler relayout_timer_canceler_;
Event<AfterLayoutEventArgs> after_layout_event_;
std::vector<std::function<void()> > after_layout_stable_action_;
- std::shared_ptr<platform::native::INativeWindowResolver>
- native_window_resolver_;
-
- // See remarks of WindowHost.
- bool retain_after_destroy_ = false;
- // See remarks of WindowHost.
- bool deleting_ = false;
-
- // We need this because calling Resolve on resolver in handler of destroy
- // event is bad and will always get the dying window. But we need to label the
- // window as destroyed so the destructor will not destroy native window
- // repeatedly. See remarks of WindowHost.
- bool native_window_destroyed_ = false;
-
std::vector<EventRevokerGuard> event_revoker_guards_;
- Window* window_control_;
- std::unique_ptr<render::WindowRenderObject> root_render_object_;
-
- Control* mouse_hover_control_;
+ Control* mouse_hover_control_ = nullptr;
- Control* focus_control_; // "focus_control_" can't be nullptr
+ Control* focus_control_;
Control* mouse_captured_control_;
diff --git a/include/cru/ui/render/Base.hpp b/include/cru/ui/render/Base.hpp
index 801d58bd..ac67349e 100644
--- a/include/cru/ui/render/Base.hpp
+++ b/include/cru/ui/render/Base.hpp
@@ -9,5 +9,4 @@ class FlexLayoutRenderObject;
class ScrollRenderObject;
class StackLayoutRenderObject;
class TextRenderObject;
-class WindowRenderObject;
} // namespace cru::ui::render
diff --git a/include/cru/ui/render/RenderObject.hpp b/include/cru/ui/render/RenderObject.hpp
index f052221e..4e5c9060 100644
--- a/include/cru/ui/render/RenderObject.hpp
+++ b/include/cru/ui/render/RenderObject.hpp
@@ -3,12 +3,13 @@
#include "MeasureRequirement.hpp"
#include "cru/common/Event.hpp"
+#include "cru/ui/Base.hpp"
+#include <cstddef>
#include <string>
#include <string_view>
namespace cru::ui::render {
-
// Render object will not destroy its children when destroyed. Control must
// manage lifecycle of its render objects. Since control will destroy its
// children when destroyed, render objects will be destroyed along with it.
@@ -38,7 +39,7 @@ namespace cru::ui::render {
// Size OnMeasureContent(const MeasureRequirement& requirement) override;
// void OnLayoutContent(const Rect& content_rect) override;
class RenderObject : public Object {
- friend WindowRenderObject;
+ friend WindowHost;
CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::render::RenderObject")
@@ -64,7 +65,7 @@ class RenderObject : public Object {
Control* GetAttachedControl() const { return control_; }
void SetAttachedControl(Control* new_control) { control_ = new_control; }
- WindowHost* GetWindowHost() const { return ui_host_; }
+ WindowHost* GetWindowHost() const { return window_host_; }
RenderObject* GetParent() const { return parent_; }
@@ -132,6 +133,11 @@ class RenderObject : public Object {
// Add offset before pass point to children.
virtual RenderObject* HitTest(const Point& point) = 0;
+ IEvent<WindowHost*>* AttachToHostEvent() { return &attach_to_host_event_; }
+ IEvent<std::nullptr_t>* DetachFromHostEvent() {
+ return &detach_from_host_event_;
+ }
+
public:
void InvalidateLayout();
void InvalidatePaint();
@@ -190,7 +196,6 @@ class RenderObject : public Object {
virtual void OnLayoutContent(const Rect& content_rect) = 0;
virtual void OnAfterLayout();
- static void NotifyAfterLayoutRecursive(RenderObject* render_object);
virtual Rect GetPaddingRect() const;
virtual Rect GetContentRect() const;
@@ -198,11 +203,11 @@ class RenderObject : public Object {
private:
void SetParent(RenderObject* new_parent);
- void SetRenderHostRecursive(WindowHost* host);
+ void SetWindowHostRecursive(WindowHost* host);
private:
Control* control_ = nullptr;
- WindowHost* ui_host_ = nullptr;
+ WindowHost* window_host_ = nullptr;
RenderObject* parent_ = nullptr;
std::vector<RenderObject*> children_{};
@@ -217,5 +222,8 @@ class RenderObject : public Object {
Thickness margin_{};
Thickness padding_{};
+
+ Event<WindowHost*> attach_to_host_event_;
+ Event<std::nullptr_t> detach_from_host_event_;
};
} // namespace cru::ui::render
diff --git a/include/cru/ui/render/WindowRenderObject.hpp b/include/cru/ui/render/WindowRenderObject.hpp
deleted file mode 100644
index 23fd8748..00000000
--- a/include/cru/ui/render/WindowRenderObject.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#pragma once
-#include "RenderObject.hpp"
-
-#include <string_view>
-
-namespace cru::ui::render {
-class WindowRenderObject : public RenderObject {
- public:
- WindowRenderObject(WindowHost* host);
- WindowRenderObject(const WindowRenderObject& other) = delete;
- WindowRenderObject(WindowRenderObject&& other) = delete;
- WindowRenderObject& operator=(const WindowRenderObject& other) = delete;
- WindowRenderObject& operator=(WindowRenderObject&& other) = delete;
- ~WindowRenderObject() override = default;
-
- RenderObject* HitTest(const Point& point) override;
-
- public:
- std::u16string_view GetName() const override;
-
- protected:
- Size OnMeasureContent(const MeasureRequirement& requirement,
- const MeasureSize& preferred_size) override;
- void OnLayoutContent(const Rect& content_rect) override;
-
- private:
- RenderObject* GetChild() const {
- return GetChildren().empty() ? nullptr : GetChildren()[0];
- }
-
- private:
- EventRevokerGuard after_layout_event_guard_;
-};
-} // namespace cru::ui::render
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index d59fd7da..045fea24 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -30,7 +30,6 @@ add_library(cru_ui STATIC
render/ScrollRenderObject.cpp
render/StackLayoutRenderObject.cpp
render/TextRenderObject.cpp
- render/WindowRenderObject.cpp
)
target_sources(cru_ui PUBLIC
${CRU_UI_INCLUDE_DIR}/Base.hpp
@@ -63,6 +62,5 @@ target_sources(cru_ui PUBLIC
${CRU_UI_INCLUDE_DIR}/render/ScrollRenderObject.hpp
${CRU_UI_INCLUDE_DIR}/render/StackLayoutRenderObject.hpp
${CRU_UI_INCLUDE_DIR}/render/TextRenderObject.hpp
- ${CRU_UI_INCLUDE_DIR}/render/WindowRenderObject.hpp
)
target_link_libraries(cru_ui PUBLIC cru_platform_native)
diff --git a/src/ui/ContentControl.cpp b/src/ui/ContentControl.cpp
index 60d944d6..19b1b06f 100644
--- a/src/ui/ContentControl.cpp
+++ b/src/ui/ContentControl.cpp
@@ -3,25 +3,19 @@
#include "cru/ui/Window.hpp"
namespace cru::ui {
-ContentControl::ContentControl()
- : child_vector_{nullptr}, child_(child_vector_[0]) {}
-
-ContentControl::~ContentControl() { delete child_; }
+Control* ContentControl::GetChild() const {
+ if (GetChildren().empty()) return nullptr;
+ return GetChildren()[0];
+}
void ContentControl::SetChild(Control* child) {
- Expects(!dynamic_cast<Window*>(child)); // Can't add a window as child.
- if (child == child_) return;
-
- const auto host = GetWindowHost();
- const auto old_child = child_;
- child_ = child;
- if (old_child) {
- old_child->_SetParent(nullptr);
- old_child->_SetDescendantWindowHost(nullptr);
+ Control* old_child = nullptr;
+ if (!GetChildren().empty()) {
+ old_child = GetChildren()[0];
+ this->RemoveChild(0);
}
if (child) {
- child->_SetParent(this);
- child->_SetDescendantWindowHost(host);
+ this->AddChild(child, 0);
}
OnChildChanged(old_child, child);
}
diff --git a/src/ui/Control.cpp b/src/ui/Control.cpp
index cd7ed0dc..13b1c780 100644
--- a/src/ui/Control.cpp
+++ b/src/ui/Control.cpp
@@ -1,10 +1,12 @@
#include "cru/ui/Control.hpp"
+#include "RoutedEventDispatch.hpp"
+#include "cru/common/Base.hpp"
#include "cru/platform/native/Cursor.hpp"
#include "cru/platform/native/UiApplication.hpp"
#include "cru/ui/Base.hpp"
#include "cru/ui/WindowHost.hpp"
-#include "RoutedEventDispatch.hpp"
+#include "cru/ui/render/RenderObject.hpp"
#include <memory>
@@ -25,49 +27,16 @@ Control::Control() {
});
}
-void Control::_SetParent(Control* parent) {
- const auto old_parent = GetParent();
- parent_ = parent;
- const auto new_parent = GetParent();
- if (old_parent != new_parent) OnParentChanged(old_parent, new_parent);
+Control::~Control() {
+ for (const auto child : children_) delete child;
}
-void Control::_SetDescendantWindowHost(WindowHost* host) {
- if (host == nullptr && ui_host_ == nullptr) return;
-
- // You can only attach or detach window.
- Expects((host != nullptr && ui_host_ == nullptr) ||
- (host == nullptr && ui_host_ != nullptr));
-
- if (host == nullptr) {
- const auto old = ui_host_;
- TraverseDescendants([old](Control* control) {
- control->ui_host_ = nullptr;
- control->OnDetachFromHost(old);
- });
- } else
- TraverseDescendants([host](Control* control) {
- control->ui_host_ = host;
- control->OnAttachToHost(host);
- });
-}
+WindowHost* Control::GetWindowHost() const { return window_host_; }
void Control::TraverseDescendants(
const std::function<void(Control*)>& predicate) {
- _TraverseDescendants(this, predicate);
-}
-
-void Control::_TraverseDescendants(
- Control* control, const std::function<void(Control*)>& predicate) {
- predicate(control);
- for (auto c : control->GetChildren()) _TraverseDescendants(c, predicate);
-}
-
-bool Control::RequestFocus() {
- auto host = GetWindowHost();
- if (host == nullptr) return false;
-
- return host->RequestFocusFor(this);
+ predicate(this);
+ for (auto c : GetChildren()) c->TraverseDescendants(predicate);
}
bool Control::HasFocus() {
@@ -84,6 +53,13 @@ bool Control::CaptureMouse() {
return host->CaptureMouseFor(this);
}
+void Control::SetFocus() {
+ auto host = GetWindowHost();
+ if (host == nullptr) return;
+
+ host->SetFocusControl(this);
+}
+
bool Control::ReleaseMouse() {
auto host = GetWindowHost();
if (host == nullptr) return false;
@@ -119,6 +95,58 @@ void Control::SetCursor(std::shared_ptr<ICursor> cursor) {
}
}
+void Control::AddChild(Control* control, const Index position) {
+ Expects(control->GetParent() ==
+ nullptr); // The control already has a parent.
+ Expects(position >= 0);
+ Expects(position <= static_cast<Index>(
+ children_.size())); // The position is out of range.
+
+ children_.insert(children_.cbegin() + position, control);
+
+ const auto old_parent = control->parent_;
+ control->parent_ = this;
+
+ OnAddChild(control, position);
+ control->OnParentChanged(old_parent, this);
+
+ if (window_host_)
+ control->TraverseDescendants([this](Control* control) {
+ control->window_host_ = window_host_;
+ control->OnAttachToHost(window_host_);
+ });
+}
+
+void Control::RemoveChild(const Index position) {
+ Expects(position >= 0);
+ Expects(position < static_cast<Index>(
+ children_.size())); // The position is out of range.
+
+ const auto i = children_.cbegin() + position;
+ const auto control = *i;
+
+ children_.erase(i);
+ control->parent_ = nullptr;
+
+ OnRemoveChild(control, position);
+ control->OnParentChanged(this, nullptr);
+
+ if (window_host_)
+ control->TraverseDescendants([this](Control* control) {
+ control->window_host_ = nullptr;
+ control->OnDetachFromHost(window_host_);
+ });
+}
+
+void Control::OnAddChild(Control* child, Index position) {
+ CRU_UNUSED(child)
+ CRU_UNUSED(position)
+}
+void Control::OnRemoveChild(Control* child, Index position) {
+ CRU_UNUSED(child)
+ CRU_UNUSED(position)
+}
+
void Control::OnParentChanged(Control* old_parent, Control* new_parent) {
CRU_UNUSED(old_parent)
CRU_UNUSED(new_parent)
diff --git a/src/ui/LayoutControl.cpp b/src/ui/LayoutControl.cpp
index 05fcdc4a..351026f9 100644
--- a/src/ui/LayoutControl.cpp
+++ b/src/ui/LayoutControl.cpp
@@ -3,51 +3,4 @@
#include "cru/ui/Window.hpp"
namespace cru::ui {
-LayoutControl::~LayoutControl() {
- for (const auto child : children_) delete child;
-}
-
-void LayoutControl::AddChild(Control* control, const Index position) {
- Expects(control->GetParent() ==
- nullptr); // The control already has a parent.
- Expects(!dynamic_cast<Window*>(control)); // Can't add a window as child.
- Expects(position >= 0);
- Expects(position <=
- static_cast<Index>(
- this->children_.size())); // The position is out of range.
-
- children_.insert(this->children_.cbegin() + position, control);
-
- control->_SetParent(this);
- control->_SetDescendantWindowHost(GetWindowHost());
-
- OnAddChild(control, position);
-}
-
-void LayoutControl::RemoveChild(const Index position) {
- Expects(position >= 0);
- Expects(position <
- static_cast<Index>(
- this->children_.size())); // The position is out of range.
-
- const auto i = children_.cbegin() + position;
- const auto child = *i;
-
- children_.erase(i);
-
- child->_SetParent(nullptr);
- child->_SetDescendantWindowHost(nullptr);
-
- OnRemoveChild(child, position);
-}
-
-void LayoutControl::OnAddChild(Control* child, const Index position) {
- CRU_UNUSED(child)
- CRU_UNUSED(position)
-}
-
-void LayoutControl::OnRemoveChild(Control* child, const Index position) {
- CRU_UNUSED(child)
- CRU_UNUSED(position)
-}
} // namespace cru::ui
diff --git a/src/ui/NoChildControl.cpp b/src/ui/NoChildControl.cpp
index 86861049..8adbe3bc 100644
--- a/src/ui/NoChildControl.cpp
+++ b/src/ui/NoChildControl.cpp
@@ -1,5 +1,3 @@
#include "cru/ui/NoChildControl.hpp"
-namespace cru::ui {
-const std::vector<Control*> NoChildControl::empty_control_vector{};
-}
+namespace cru::ui {}
diff --git a/src/ui/Window.cpp b/src/ui/Window.cpp
index a8cb315b..6d507858 100644
--- a/src/ui/Window.cpp
+++ b/src/ui/Window.cpp
@@ -1,28 +1,31 @@
#include "cru/ui/Window.hpp"
-#include "cru/ui/render/WindowRenderObject.hpp"
+#include "cru/common/Base.hpp"
#include "cru/ui/WindowHost.hpp"
+#include "cru/ui/render/Base.hpp"
+#include "cru/ui/render/StackLayoutRenderObject.hpp"
namespace cru::ui {
-Window* Window::CreateOverlapped() {
- return new Window(tag_overlapped_constructor{});
-}
+Window* Window::CreateOverlapped() { return new Window(); }
-Window::Window(tag_overlapped_constructor) {
- managed_ui_host_ = std::make_unique<WindowHost>(this);
+Window::Window() : render_object_(new render::StackLayoutRenderObject()) {
+ window_host_ = std::make_unique<WindowHost>(this);
}
-Window::~Window() {
- // explicit destroy ui host first.
- managed_ui_host_.reset();
-}
+Window::~Window() {}
std::u16string_view Window::GetControlType() const { return control_type; }
-render::RenderObject* Window::GetRenderObject() const { return render_object_; }
+render::RenderObject* Window::GetRenderObject() const {
+ return render_object_.get();
+}
+
+void Window::OnAddChild(Control* child, Index position) {
+ render_object_->AddChild(child->GetRenderObject(), position);
+}
-void Window::OnChildChanged(Control* old_child, Control* new_child) {
- if (old_child) render_object_->RemoveChild(0);
- if (new_child) render_object_->AddChild(new_child->GetRenderObject(), 0);
+void Window::OnRemoveChild(Control* child, Index position) {
+ CRU_UNUSED(child);
+ render_object_->RemoveChild(position);
}
} // namespace cru::ui
diff --git a/src/ui/WindowHost.cpp b/src/ui/WindowHost.cpp
index d3dec422..1dba4404 100644
--- a/src/ui/WindowHost.cpp
+++ b/src/ui/WindowHost.cpp
@@ -9,7 +9,9 @@
#include "cru/ui/DebugFlags.hpp"
#include "cru/ui/Window.hpp"
#include "cru/ui/render/MeasureRequirement.hpp"
-#include "cru/ui/render/WindowRenderObject.hpp"
+#include "cru/ui/render/RenderObject.hpp"
+
+#include <cstddef>
namespace cru::ui {
using platform::native::INativeWindow;
@@ -97,25 +99,18 @@ inline void BindNativeEvent(
}
} // namespace
-WindowHost::WindowHost(Window* window)
- : window_control_(window),
- mouse_hover_control_(nullptr),
- focus_control_(window),
- mouse_captured_control_(nullptr) {
+WindowHost::WindowHost(Control* root_control) : root_control_(root_control) {
const auto ui_application = IUiApplication::GetInstance();
- native_window_resolver_ = ui_application->CreateWindow(nullptr);
-
- const auto native_window = native_window_resolver_->Resolve();
-
- auto input_method_context =
- ui_application->GetInputMethodManager()->GetContext(native_window);
- input_method_context->DisableIME();
+ auto native_window = ui_application->CreateWindow(nullptr);
+ native_window_ = native_window;
- window->ui_host_ = this;
+ root_control_->TraverseDescendants([this](Control* control) {
+ control->window_host_ = this;
+ control->OnAttachToHost(this);
+ });
- root_render_object_ = std::make_unique<render::WindowRenderObject>(this);
- root_render_object_->SetAttachedControl(window);
- window->render_object_ = root_render_object_.get();
+ root_render_object_ = root_control->GetRenderObject();
+ root_render_object_->SetWindowHostRecursive(this);
BindNativeEvent(this, native_window, native_window->DestroyEvent(),
&WindowHost::OnNativeDestroy, event_revoker_guards_);
@@ -140,34 +135,24 @@ WindowHost::WindowHost(Window* window)
}
WindowHost::~WindowHost() {
- deleting_ = true;
- window_control_->TraverseDescendants(
- [this](Control* control) { control->OnDetachFromHost(this); });
- if (!native_window_destroyed_) {
- const auto native_window = native_window_resolver_->Resolve();
- if (native_window) {
- native_window->Close();
- }
+ if (native_window_) {
+ native_window_->Close();
}
}
void WindowHost::InvalidatePaint() {
- if (const auto native_window = native_window_resolver_->Resolve())
- native_window->RequestRepaint();
+ if (native_window_) native_window_->RequestRepaint();
}
void WindowHost::InvalidateLayout() {
if constexpr (debug_flags::layout)
log::TagDebug(log_tag, u"A relayout is requested.");
if (!need_layout_) {
- platform::native::IUiApplication::GetInstance()->SetImmediate(
- [resolver = this->CreateResolver()] {
- if (const auto host = resolver.Resolve()) {
- host->Relayout();
- host->need_layout_ = false;
- host->InvalidatePaint();
- }
- });
+ platform::native::IUiApplication::GetInstance()->SetImmediate([this] {
+ Relayout();
+ need_layout_ = false;
+ InvalidatePaint();
+ });
need_layout_ = true;
}
}
@@ -183,15 +168,17 @@ void WindowHost::SetLayoutPreferToFillWindow(bool value) {
}
void WindowHost::Relayout() {
- const auto native_window = native_window_resolver_->Resolve();
- const auto client_size = native_window
- ? native_window->GetClientSize()
- : Size{100, 100}; // a reasonable assumed size
+ const auto available_size =
+ native_window_ ? native_window_->GetClientSize()
+ : Size{100, 100}; // a reasonable assumed size
+ Relayout(available_size);
+}
+void WindowHost::Relayout(const Size& available_size) {
root_render_object_->Measure(
- render::MeasureRequirement{client_size,
+ render::MeasureRequirement{available_size,
IsLayoutPreferToFillWindow()
- ? render::MeasureSize(client_size)
+ ? render::MeasureSize(available_size)
: render::MeasureSize::NotSpecified()},
render::MeasureSize::NotSpecified());
root_render_object_->Layout(Point{});
@@ -202,11 +189,11 @@ void WindowHost::Relayout() {
log::TagDebug(log_tag, u"A relayout is finished.");
}
-bool WindowHost::RequestFocusFor(Control* control) {
- Expects(control != nullptr); // The control to request focus can't be null.
- // You can set it as the window.
+Control* WindowHost::GetFocusControl() { return focus_control_; }
- if (focus_control_ == control) return true;
+void WindowHost::SetFocusControl(Control* control) {
+ if (focus_control_ == control) return;
+ if (control == nullptr) control = root_control_;
const auto old_focus_control = focus_control_;
@@ -217,15 +204,10 @@ bool WindowHost::RequestFocusFor(Control* control) {
DispatchEvent(event_names::GainFocus, control, &Control::GainFocusEvent,
nullptr, false);
-
- return true;
}
-Control* WindowHost::GetFocusControl() { return focus_control_; }
-
bool WindowHost::CaptureMouseFor(Control* control) {
- const auto native_window = native_window_resolver_->Resolve();
- if (!native_window) return false;
+ if (!native_window_) return false;
if (control == mouse_captured_control_) return true;
@@ -236,7 +218,7 @@ bool WindowHost::CaptureMouseFor(Control* control) {
if (old_capture_control != mouse_hover_control_) {
DispatchMouseHoverControlChangeEvent(
old_capture_control, mouse_hover_control_,
- native_window->GetMousePosition(), true, false);
+ native_window_->GetMousePosition(), true, false);
}
UpdateCursor();
return true;
@@ -247,7 +229,7 @@ bool WindowHost::CaptureMouseFor(Control* control) {
mouse_captured_control_ = control;
DispatchMouseHoverControlChangeEvent(
mouse_hover_control_, mouse_captured_control_,
- native_window->GetMousePosition(), false, true);
+ native_window_->GetMousePosition(), false, true);
UpdateCursor();
return true;
}
@@ -266,8 +248,8 @@ void WindowHost::RunAfterLayoutStable(std::function<void()> action) {
void WindowHost::OnNativeDestroy(INativeWindow* window, std::nullptr_t) {
CRU_UNUSED(window)
- native_window_destroyed_ = true;
- if (!deleting_ && !retain_after_destroy_) delete window_control_;
+ this->relayout_timer_canceler_.Reset();
+ this->native_window_ = nullptr;
}
void WindowHost::OnNativePaint(INativeWindow* window, std::nullptr_t) {
@@ -399,9 +381,9 @@ void WindowHost::DispatchMouseHoverControlChangeEvent(Control* old_control,
}
void WindowHost::UpdateCursor() {
- if (const auto native_window = native_window_resolver_->Resolve()) {
+ if (native_window_) {
const auto capture = GetMouseCaptureControl();
- native_window->SetCursor(
+ native_window_->SetCursor(
(capture ? capture : GetMouseHoverControl())->GetInheritedCursor());
}
}
@@ -413,6 +395,6 @@ Control* WindowHost::HitTest(const Point& point) {
Ensures(control);
return control;
}
- return window_control_;
+ return root_control_;
}
} // namespace cru::ui
diff --git a/src/ui/controls/TextControlService.hpp b/src/ui/controls/TextControlService.hpp
index 8c1bd32f..33a6bc36 100644
--- a/src/ui/controls/TextControlService.hpp
+++ b/src/ui/controls/TextControlService.hpp
@@ -61,7 +61,7 @@ class TextControlService : public Object {
void SetEditable(bool editable) {
this->editable_ = editable;
- this->input_method_context_.reset();
+ if (!editable) CancelComposition();
}
std::u16string GetText() { return this->text_; }
@@ -69,8 +69,8 @@ class TextControlService : public Object {
void SetText(std::u16string text, bool stop_composition = false) {
this->text_ = std::move(text);
CoerceSelection();
- if (stop_composition && this->input_method_context_) {
- this->input_method_context_->CancelComposition();
+ if (stop_composition) {
+ CancelComposition();
}
SyncTextRenderObject();
}
@@ -83,8 +83,8 @@ class TextControlService : public Object {
}
this->text_.insert(this->text_.cbegin() + position, text.begin(),
text.end());
- if (stop_composition && this->input_method_context_) {
- this->input_method_context_->CancelComposition();
+ if (stop_composition) {
+ CancelComposition();
}
SyncTextRenderObject();
}
@@ -129,15 +129,30 @@ class TextControlService : public Object {
this->text_.erase(this->text_.cbegin() + range.GetStart(),
this->text_.cbegin() + range.GetEnd());
this->CoerceSelection();
- if (stop_composition && this->input_method_context_) {
- this->input_method_context_->CancelComposition();
+ if (stop_composition) {
+ CancelComposition();
}
this->SyncTextRenderObject();
}
+ platform::native::IInputMethodContext* GetInputMethodContext() {
+ WindowHost* host = this->control_->GetWindowHost();
+ if (!host) return nullptr;
+ platform::native::INativeWindow* native_window = host->GetNativeWindow();
+ if (!native_window) return nullptr;
+ return native_window->GetInputMethodContext();
+ }
+
+ void CancelComposition() {
+ auto input_method_context = GetInputMethodContext();
+ if (input_method_context == nullptr) return;
+ input_method_context->CancelComposition();
+ }
+
std::optional<platform::native::CompositionText> GetCompositionInfo() {
- if (this->input_method_context_ == nullptr) return std::nullopt;
- auto composition_info = this->input_method_context_->GetCompositionText();
+ auto input_method_context = GetInputMethodContext();
+ if (input_method_context == nullptr) return std::nullopt;
+ auto composition_info = input_method_context->GetCompositionText();
if (composition_info.text.empty()) return std::nullopt;
return composition_info;
}
@@ -319,12 +334,11 @@ class TextControlService : public Object {
}
void MouseDownHandler(event::MouseButtonEventArgs& args) {
- this->control_->RequestFocus();
if (this->select_down_button_.has_value()) {
return;
} else {
+ this->control_->SetFocus();
if (!this->control_->CaptureMouse()) return;
- if (!this->control_->RequestFocus()) return;
const auto text_render_object = this->GetTextRenderObject();
this->select_down_button_ = args.GetButton();
const auto result = text_render_object->TextHitTest(
@@ -408,33 +422,35 @@ class TextControlService : public Object {
void GainFocusHandler(event::FocusChangeEventArgs& args) {
CRU_UNUSED(args);
if (editable_) {
- WindowHost* ui_host = this->control_->GetWindowHost();
- auto window = ui_host->GetNativeWindowResolver()->Resolve();
- if (window == nullptr) return;
- input_method_context_ =
- GetUiApplication()->GetInputMethodManager()->GetContext(window);
- input_method_context_->EnableIME();
+ auto input_method_context = GetInputMethodContext();
+ if (input_method_context == nullptr) return;
+ input_method_context->EnableIME();
auto sync = [this](std::nullptr_t) {
this->SyncTextRenderObject();
ScrollToCaret();
};
- input_method_context_->CompositionStartEvent()->AddHandler(
- [this](std::nullptr_t) { this->DeleteSelectedText(); });
- input_method_context_->CompositionEvent()->AddHandler(sync);
- input_method_context_->CompositionEndEvent()->AddHandler(sync);
- input_method_context_->TextEvent()->AddHandler(
- [this](const std::u16string_view& text) {
- if (text == u"\b") return;
- this->ReplaceSelectedText(text);
- });
+ input_method_context_event_guard_ +=
+ input_method_context->CompositionStartEvent()->AddHandler(
+ [this](std::nullptr_t) { this->DeleteSelectedText(); });
+ input_method_context_event_guard_ +=
+ input_method_context->CompositionEvent()->AddHandler(sync);
+ input_method_context_event_guard_ +=
+ input_method_context->CompositionEndEvent()->AddHandler(sync);
+ input_method_context_event_guard_ +=
+ input_method_context->TextEvent()->AddHandler(
+ [this](const std::u16string_view& text) {
+ if (text == u"\b") return;
+ this->ReplaceSelectedText(text);
+ });
}
}
void LoseFocusHandler(event::FocusChangeEventArgs& args) {
if (!args.IsWindow()) this->AbortSelection();
- if (input_method_context_) {
- input_method_context_->DisableIME();
- input_method_context_.reset();
+ input_method_context_event_guard_.Clear();
+ auto input_method_context = GetInputMethodContext();
+ if (input_method_context) {
+ input_method_context->DisableIME();
}
SyncTextRenderObject();
}
@@ -442,6 +458,7 @@ class TextControlService : public Object {
private:
gsl::not_null<TControl*> control_;
EventRevokerListGuard event_guard_;
+ EventRevokerListGuard input_method_context_event_guard_;
std::u16string text_;
TextRange selection_;
@@ -457,7 +474,5 @@ class TextControlService : public Object {
// nullopt means not selecting
std::optional<MouseButton> select_down_button_;
-
- std::unique_ptr<platform::native::IInputMethodContext> input_method_context_;
}; // namespace cru::ui::controls
} // namespace cru::ui::controls
diff --git a/src/ui/render/RenderObject.cpp b/src/ui/render/RenderObject.cpp
index 5266daaf..fd0c7712 100644
--- a/src/ui/render/RenderObject.cpp
+++ b/src/ui/render/RenderObject.cpp
@@ -24,7 +24,7 @@ void RenderObject::AddChild(RenderObject* render_object, const Index position) {
children_.insert(children_.cbegin() + position, render_object);
render_object->SetParent(this);
- render_object->SetRenderHostRecursive(GetWindowHost());
+ render_object->SetWindowHostRecursive(GetWindowHost());
OnAddChild(render_object, position);
}
@@ -37,7 +37,7 @@ void RenderObject::RemoveChild(const Index position) {
const auto removed_child = *i;
children_.erase(i);
removed_child->SetParent(nullptr);
- removed_child->SetRenderHostRecursive(nullptr);
+ removed_child->SetWindowHostRecursive(nullptr);
OnRemoveChild(removed_child, position);
}
@@ -269,11 +269,11 @@ void RenderObject::SetParent(RenderObject* new_parent) {
}
void RenderObject::InvalidateLayout() {
- if (ui_host_ != nullptr) ui_host_->InvalidateLayout();
+ if (window_host_ != nullptr) window_host_->InvalidateLayout();
}
void RenderObject::InvalidatePaint() {
- if (ui_host_ != nullptr) ui_host_->InvalidatePaint();
+ if (window_host_ != nullptr) window_host_->InvalidatePaint();
}
constexpr std::u16string_view kUnamedName(u"UNNAMED");
@@ -297,17 +297,16 @@ std::u16string RenderObject::GetDebugPathInTree() const {
return result;
}
-void RenderObject::NotifyAfterLayoutRecursive(RenderObject* render_object) {
- render_object->OnAfterLayout();
- for (const auto o : render_object->GetChildren()) {
- NotifyAfterLayoutRecursive(o);
+void RenderObject::SetWindowHostRecursive(WindowHost* host) {
+ if (window_host_ != nullptr) {
+ detach_from_host_event_.Raise(nullptr);
+ }
+ window_host_ = host;
+ if (host != nullptr) {
+ attach_to_host_event_.Raise(nullptr);
}
-}
-
-void RenderObject::SetRenderHostRecursive(WindowHost* host) {
- ui_host_ = host;
for (const auto child : GetChildren()) {
- child->SetRenderHostRecursive(host);
+ child->SetWindowHostRecursive(host);
}
}
} // namespace cru::ui::render
diff --git a/src/ui/render/WindowRenderObject.cpp b/src/ui/render/WindowRenderObject.cpp
deleted file mode 100644
index 23cca12e..00000000
--- a/src/ui/render/WindowRenderObject.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "cru/ui/render/WindowRenderObject.hpp"
-
-#include "../Helper.hpp"
-#include "cru/platform/graph/util/Painter.hpp"
-#include "cru/ui/WindowHost.hpp"
-
-namespace cru::ui::render {
-WindowRenderObject::WindowRenderObject(WindowHost* host) {
- SetChildMode(ChildMode::Single);
- ui_host_ = host;
- after_layout_event_guard_.Reset(host->AfterLayoutEvent()->AddHandler(
- [this](auto) { NotifyAfterLayoutRecursive(this); }));
-}
-
-RenderObject* WindowRenderObject::HitTest(const Point& point) {
- if (const auto child = GetChild()) {
- auto offset = child->GetOffset();
- Point p{point.x - offset.x, point.y - offset.y};
- const auto result = child->HitTest(p);
- if (result != nullptr) {
- return result;
- }
- }
- return Rect{Point{}, GetSize()}.IsPointInside(point) ? this : nullptr;
-}
-
-std::u16string_view WindowRenderObject::GetName() const {
- return u"WindowRenderObject";
-}
-
-Size WindowRenderObject::OnMeasureContent(const MeasureRequirement& requirement,
- const MeasureSize& preferred_size) {
- if (const auto child = GetChild()) {
- child->Measure(requirement, preferred_size);
- return child->GetSize();
- } else {
- return Size{};
- }
-}
-
-void WindowRenderObject::OnLayoutContent(const Rect& content_rect) {
- if (const auto child = GetChild()) child->Layout(content_rect.GetLeftTop());
-}
-} // namespace cru::ui::render
diff --git a/src/win/native/UiApplication.cpp b/src/win/native/UiApplication.cpp
index 60ff8e8c..87ef0b81 100644
--- a/src/win/native/UiApplication.cpp
+++ b/src/win/native/UiApplication.cpp
@@ -43,7 +43,6 @@ WinUiApplication::WinUiApplication() {
timer_manager_ = std::make_unique<TimerManager>(god_window_.get());
window_manager_ = std::make_unique<WindowManager>(this);
cursor_manager_ = std::make_unique<WinCursorManager>();
- input_method_manager_ = std::make_unique<WinInputMethodManager>(this);
}
WinUiApplication::~WinUiApplication() { instance = nullptr; }
@@ -116,8 +115,4 @@ cru::platform::graph::IGraphFactory* WinUiApplication::GetGraphFactory() {
ICursorManager* WinUiApplication::GetCursorManager() {
return cursor_manager_.get();
}
-
-IInputMethodManager* WinUiApplication::GetInputMethodManager() {
- return input_method_manager_.get();
-}
} // namespace cru::platform::native::win
diff --git a/src/win/native/Window.cpp b/src/win/native/Window.cpp
index d9237c4f..1a6fcb07 100644
--- a/src/win/native/Window.cpp
+++ b/src/win/native/Window.cpp
@@ -55,6 +55,7 @@ WinNativeWindow::WinNativeWindow(WinUiApplication* application,
window_render_target_->SetDpi(dpi_, dpi_);
input_method_context_ = std::make_unique<WinInputMethodContext>(this);
+ input_method_context_->DisableIME();
}
WinNativeWindow::~WinNativeWindow() {