From df4df679e157f974773dad7776b204e9d4f3009e Mon Sep 17 00:00:00 2001 From: crupest Date: Wed, 28 Oct 2020 21:28:15 +0800 Subject: ... --- include/cru/platform/native/Base.hpp | 11 ++--- include/cru/platform/native/Cursor.hpp | 1 - include/cru/platform/native/InputMethod.hpp | 6 --- include/cru/platform/native/Keyboard.hpp | 4 +- include/cru/platform/native/UiApplication.hpp | 6 +-- include/cru/platform/native/Window.hpp | 16 ++----- include/cru/ui/WindowHost.hpp | 24 ---------- include/cru/win/native/Base.hpp | 4 +- include/cru/win/native/InputMethod.hpp | 21 ++------- include/cru/win/native/UiApplication.hpp | 6 +-- include/cru/win/native/Window.hpp | 35 +++------------ src/win/native/InputMethod.cpp | 65 ++++++--------------------- src/win/native/UiApplication.cpp | 8 ++-- src/win/native/Window.cpp | 26 +++++------ 14 files changed, 48 insertions(+), 185 deletions(-) diff --git a/include/cru/platform/native/Base.hpp b/include/cru/platform/native/Base.hpp index bba7b960..c3e87439 100644 --- a/include/cru/platform/native/Base.hpp +++ b/include/cru/platform/native/Base.hpp @@ -1,23 +1,18 @@ #pragma once +#include "Keyboard.hpp" #include "cru/common/Base.hpp" #include "cru/common/Bitmask.hpp" #include "cru/platform/graph/Base.hpp" -#include "Keyboard.hpp" + +#include "../Resource.hpp" namespace cru::platform::native { struct ICursor; struct ICursorManager; struct IUiApplication; struct INativeWindow; -struct INativeWindowResolver; -struct IInputMethodManager; struct IInputMethodContext; -struct Dpi { - float x; - float y; -}; - namespace details { struct TagMouseButton {}; } // namespace details diff --git a/include/cru/platform/native/Cursor.hpp b/include/cru/platform/native/Cursor.hpp index 6c8f8068..447cd694 100644 --- a/include/cru/platform/native/Cursor.hpp +++ b/include/cru/platform/native/Cursor.hpp @@ -1,5 +1,4 @@ #pragma once -#include "../Resource.hpp" #include "Base.hpp" #include diff --git a/include/cru/platform/native/InputMethod.hpp b/include/cru/platform/native/InputMethod.hpp index 6f222a43..de752417 100644 --- a/include/cru/platform/native/InputMethod.hpp +++ b/include/cru/platform/native/InputMethod.hpp @@ -1,5 +1,4 @@ #pragma once -#include "../Resource.hpp" #include "Base.hpp" #include "cru/common/Event.hpp" @@ -52,11 +51,6 @@ struct IInputMethodContext : virtual INativeResource { virtual IEvent* TextEvent() = 0; }; - -struct IInputMethodManager : virtual INativeResource { - virtual std::unique_ptr GetContext( - INativeWindow* window) = 0; -}; } // namespace cru::platform::native template <> diff --git a/include/cru/platform/native/Keyboard.hpp b/include/cru/platform/native/Keyboard.hpp index 8f53c5d6..67a35c8a 100644 --- a/include/cru/platform/native/Keyboard.hpp +++ b/include/cru/platform/native/Keyboard.hpp @@ -1,7 +1,9 @@ #pragma once -#include #include "cru/common/Bitmask.hpp" +#include +#include + namespace cru::platform::native { // Because of the complexity of keyboard layout, I only add code in US keyboard // layout, the most widely used layout in China. We should try to make it easy diff --git a/include/cru/platform/native/UiApplication.hpp b/include/cru/platform/native/UiApplication.hpp index 4c1b3456..2b1b047a 100644 --- a/include/cru/platform/native/UiApplication.hpp +++ b/include/cru/platform/native/UiApplication.hpp @@ -1,7 +1,5 @@ #pragma once -#include "../Resource.hpp" #include "Base.hpp" -#include "cru/common/Base.hpp" #include #include @@ -45,13 +43,11 @@ struct IUiApplication : public virtual INativeResource { virtual void CancelTimer(long long id) = 0; virtual std::vector GetAllWindow() = 0; - virtual std::shared_ptr CreateWindow( - INativeWindow* parent) = 0; + virtual INativeWindow* CreateWindow(INativeWindow* parent) = 0; virtual cru::platform::graph::IGraphFactory* GetGraphFactory() = 0; virtual ICursorManager* GetCursorManager() = 0; - virtual IInputMethodManager* GetInputMethodManager() = 0; }; class TimerAutoCanceler { diff --git a/include/cru/platform/native/Window.hpp b/include/cru/platform/native/Window.hpp index 1fcac1fc..c8abdeac 100644 --- a/include/cru/platform/native/Window.hpp +++ b/include/cru/platform/native/Window.hpp @@ -1,6 +1,6 @@ #pragma once -#include "../Resource.hpp" #include "Base.hpp" + #include "cru/common/Event.hpp" #include @@ -8,14 +8,7 @@ namespace cru::platform::native { // Represents a native window, which exposes some low-level events and // operations. -// -// Usually you save an INativeWindowResolver after creating a window. Because -// window may be destroyed when user do certain actions like click the close -// button. Then the INativeWindow instance is destroyed and -// INativeWindowResolver::Resolve return nullptr to indicate the fact. struct INativeWindow : virtual INativeResource { - virtual std::shared_ptr GetResolver() = 0; - virtual void Close() = 0; virtual INativeWindow* GetParent() = 0; @@ -47,6 +40,7 @@ struct INativeWindow : virtual INativeResource { // Remember to call EndDraw on return value and destroy it. virtual std::unique_ptr BeginPaint() = 0; + // Don't use this instance after receive this event. virtual IEvent* DestroyEvent() = 0; virtual IEvent* PaintEvent() = 0; virtual IEvent* ResizeEvent() = 0; @@ -57,11 +51,7 @@ struct INativeWindow : virtual INativeResource { virtual IEvent* MouseUpEvent() = 0; virtual IEvent* KeyDownEvent() = 0; virtual IEvent* KeyUpEvent() = 0; -}; -// See INativeWindow for more info. -struct INativeWindowResolver : virtual INativeResource { - // Think twice before you save the return value. - virtual INativeWindow* Resolve() = 0; + virtual IInputMethodContext* GetInputMethodContext() = 0; }; } // namespace cru::platform::native diff --git a/include/cru/ui/WindowHost.hpp b/include/cru/ui/WindowHost.hpp index 64116590..83ef2f64 100644 --- a/include/cru/ui/WindowHost.hpp +++ b/include/cru/ui/WindowHost.hpp @@ -8,30 +8,6 @@ namespace cru::ui { struct AfterLayoutEventArgs {}; - -// The host of all controls and render objects. -// -// 3 situations on destroy: -// 1. Native window destroyed, IsRetainAfterDestroy: false: -// OnNativeDestroy(set native_window_destroyed_ to true, call ~Window due to -// deleting_ is false and IsRetainAfterDestroy is false) -> ~Window -> -// ~WindowHost(not destroy native window repeatedly due to native_window_destroyed_ -// is true) -// 2. Native window destroyed, IsRetainAfterDestroy: true: -// OnNativeDestroy(set native_window_destroyed_ to true, not call ~Window -// because deleting_ is false and IsRetainAfterDestroy is true) -// then, ~Window -> ~WindowHost(not destroy native window repeatedly due to -// native_window_destroyed_ is true) -// 3. Native window not destroyed, ~Window is called: -// ~Window -> ~WindowHost(set deleting_ to true, destroy native window -// due to native_window_destroyed is false) -> OnNativeDestroy(not call ~Window -// due to deleting_ is true and IsRetainAfterDestroy is whatever) -// In conclusion: -// 1. Set native_window_destroyed_ to true at the beginning of OnNativeDestroy. -// 2. Set deleting_ to true at the beginning of ~WindowHost. -// 3. Destroy native window when native_window_destroy_ is false in ~Window. -// 4. Delete Window when deleting_ is false and IsRetainAfterDestroy is false in -// OnNativeDestroy. class WindowHost : public Object, public SelfResolvable { CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::WindowHost") diff --git a/include/cru/win/native/Base.hpp b/include/cru/win/native/Base.hpp index 7ddc6b54..881dd8b1 100644 --- a/include/cru/win/native/Base.hpp +++ b/include/cru/win/native/Base.hpp @@ -11,8 +11,6 @@ class WinCursorManager; class WindowClass; class WindowManager; class WinNativeWindow; -class WinNativeWindowResolver; class WinUiApplication; -class WinInputMethodManager; -class WinInputMethodContextRef; +class WinInputMethodContext; } // namespace cru::platform::native::win diff --git a/include/cru/win/native/InputMethod.hpp b/include/cru/win/native/InputMethod.hpp index 113f460d..f3dc15c0 100644 --- a/include/cru/win/native/InputMethod.hpp +++ b/include/cru/win/native/InputMethod.hpp @@ -72,31 +72,16 @@ class WinInputMethodContext : public WinNativeResource, std::u16string GetResultString(); - std::optional TryGetHIMC(); + AutoHIMC GetHIMC(); private: - std::shared_ptr native_window_resolver_; + WinNativeWindow* native_window_; - std::vector event_revoker_guards_; + EventRevokerListGuard event_guard_; Event composition_start_event_; Event composition_end_event_; Event composition_event_; Event text_event_; }; - -class WinInputMethodManager : public WinNativeResource, - public virtual IInputMethodManager { - public: - WinInputMethodManager(WinUiApplication* application); - - CRU_DELETE_COPY(WinInputMethodManager) - CRU_DELETE_MOVE(WinInputMethodManager) - - ~WinInputMethodManager() override; - - public: - std::unique_ptr GetContext( - INativeWindow* window) override; -}; } // namespace cru::platform::native::win diff --git a/include/cru/win/native/UiApplication.hpp b/include/cru/win/native/UiApplication.hpp index 328a6b84..170be532 100644 --- a/include/cru/win/native/UiApplication.hpp +++ b/include/cru/win/native/UiApplication.hpp @@ -1,6 +1,7 @@ #pragma once #include "Resource.hpp" +#include "cru/platform/native/Base.hpp" #include "cru/platform/native/UiApplication.hpp" #include @@ -40,8 +41,7 @@ class WinUiApplication : public WinNativeResource, void CancelTimer(long long id) override; std::vector GetAllWindow() override; - std::shared_ptr CreateWindow( - INativeWindow* parent) override; + INativeWindow* CreateWindow(INativeWindow* parent) override; cru::platform::graph::IGraphFactory* GetGraphFactory() override; @@ -50,7 +50,6 @@ class WinUiApplication : public WinNativeResource, } ICursorManager* GetCursorManager() override; - IInputMethodManager* GetInputMethodManager() override; HINSTANCE GetInstanceHandle() const { return instance_handle_; } @@ -69,7 +68,6 @@ class WinUiApplication : public WinNativeResource, std::unique_ptr window_manager_; std::unique_ptr cursor_manager_; - std::unique_ptr input_method_manager_; std::vector> quit_handlers_; }; diff --git a/include/cru/win/native/Window.hpp b/include/cru/win/native/Window.hpp index ecc0dd04..6bf71601 100644 --- a/include/cru/win/native/Window.hpp +++ b/include/cru/win/native/Window.hpp @@ -3,6 +3,7 @@ #include "WindowNativeMessageEventArgs.hpp" #include "cru/platform/GraphBase.hpp" +#include "cru/platform/native/Base.hpp" #include "cru/platform/native/Window.hpp" #include "cru/win/graph/direct/WindowRenderTarget.hpp" @@ -22,10 +23,6 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow { ~WinNativeWindow() override; public: - std::shared_ptr GetResolver() override { - return std::static_pointer_cast(resolver_); - } - void Close() override; WinNativeWindow* GetParent() override { return parent_window_; } @@ -81,6 +78,8 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow { return &native_message_event_; } + IInputMethodContext* GetInputMethodContext() override; + // Get the handle of the window. Return null if window is invalid. HWND GetWindowHandle() const { return hwnd_; } @@ -148,8 +147,6 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow { // again. bool sync_flag_ = false; - std::shared_ptr resolver_; - HWND hwnd_; WinNativeWindow* parent_window_; @@ -163,6 +160,8 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow { std::shared_ptr cursor_; + std::unique_ptr input_method_context_; + Event destroy_event_; Event paint_event_; Event resize_event_; @@ -176,28 +175,4 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow { Event native_message_event_; }; - -class WinNativeWindowResolver : public WinNativeResource, - public virtual INativeWindowResolver { - friend WinNativeWindow::~WinNativeWindow(); - - public: - WinNativeWindowResolver(WinNativeWindow* window) : window_(window) {} - - CRU_DELETE_COPY(WinNativeWindowResolver) - CRU_DELETE_MOVE(WinNativeWindowResolver) - - ~WinNativeWindowResolver() override = default; - - public: - INativeWindow* Resolve() override { return window_; } - - private: - void Reset(); - - private: - WinNativeWindow* window_; -}; - -WinNativeWindow* Resolve(gsl::not_null resolver); } // namespace cru::platform::native::win diff --git a/src/win/native/InputMethod.cpp b/src/win/native/InputMethod.cpp index d976a8ba..45c5f8da 100644 --- a/src/win/native/InputMethod.cpp +++ b/src/win/native/InputMethod.cpp @@ -145,30 +145,23 @@ CompositionText GetCompositionInfo(HIMC imm_context) { WinInputMethodContext::WinInputMethodContext( gsl::not_null window) - : native_window_resolver_(window->GetResolver()) { - event_revoker_guards_.push_back( - EventRevokerGuard(window->NativeMessageEvent()->AddHandler( - std::bind(&WinInputMethodContext::OnWindowNativeMessage, this, - std::placeholders::_1)))); + : native_window_(window) { + event_guard_ += window->NativeMessageEvent()->AddHandler( + std::bind(&WinInputMethodContext::OnWindowNativeMessage, this, + std::placeholders::_1)); } WinInputMethodContext::~WinInputMethodContext() {} void WinInputMethodContext::EnableIME() { - const auto native_window = Resolve(native_window_resolver_.get()); - if (native_window == nullptr) return; - const auto hwnd = native_window->GetWindowHandle(); - + const auto hwnd = native_window_->GetWindowHandle(); if (::ImmAssociateContextEx(hwnd, nullptr, IACE_DEFAULT) == FALSE) { log::TagWarn(log_tag, u"Failed to enable ime."); } } void WinInputMethodContext::DisableIME() { - const auto native_window = Resolve(native_window_resolver_.get()); - if (native_window == nullptr) return; - const auto hwnd = native_window->GetWindowHandle(); - + const auto hwnd = native_window_->GetWindowHandle(); AutoHIMC himc{hwnd}; if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_COMPLETE, 0)) { @@ -182,46 +175,32 @@ void WinInputMethodContext::DisableIME() { } void WinInputMethodContext::CompleteComposition() { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return; - auto himc = *std::move(optional_himc); - + auto himc = GetHIMC(); if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_COMPLETE, 0)) { log::TagWarn(log_tag, u"Failed to complete composition."); } } void WinInputMethodContext::CancelComposition() { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return; - auto himc = *std::move(optional_himc); - + auto himc = GetHIMC(); if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_CANCEL, 0)) { log::TagWarn(log_tag, u"Failed to complete composition."); } } CompositionText WinInputMethodContext::GetCompositionText() { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return CompositionText{}; - auto himc = *std::move(optional_himc); - + auto himc = GetHIMC(); return GetCompositionInfo(himc.Get()); } void WinInputMethodContext::SetCandidateWindowPosition(const Point& point) { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return; - auto himc = *std::move(optional_himc); + auto himc = GetHIMC(); ::CANDIDATEFORM form; form.dwIndex = 1; form.dwStyle = CFS_CANDIDATEPOS; - auto window = - dynamic_cast(this->native_window_resolver_->Resolve()); - form.ptCurrentPos = - window == nullptr ? POINT{0, 0} : window->DipToPixel(point); + form.ptCurrentPos = native_window_->DipToPixel(point); if (!::ImmSetCandidateWindow(himc.Get(), &form)) log::TagDebug(log_tag, @@ -287,29 +266,13 @@ void WinInputMethodContext::OnWindowNativeMessage( } std::u16string WinInputMethodContext::GetResultString() { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return u""; - auto himc = *std::move(optional_himc); - + auto himc = GetHIMC(); auto result = win::GetResultString(himc.Get()); return result; } -std::optional WinInputMethodContext::TryGetHIMC() { - const auto native_window = Resolve(native_window_resolver_.get()); - if (native_window == nullptr) return std::nullopt; - const auto hwnd = native_window->GetWindowHandle(); +AutoHIMC WinInputMethodContext::GetHIMC() { + const auto hwnd = native_window_->GetWindowHandle(); return AutoHIMC{hwnd}; } - -WinInputMethodManager::WinInputMethodManager(WinUiApplication*) {} - -WinInputMethodManager::~WinInputMethodManager() {} - -std::unique_ptr WinInputMethodManager::GetContext( - INativeWindow* window) { - Expects(window); - const auto w = CheckPlatform(window, GetPlatformId()); - return std::make_unique(w); -} } // namespace cru::platform::native::win diff --git a/src/win/native/UiApplication.cpp b/src/win/native/UiApplication.cpp index 3f7a0cf5..60ff8e8c 100644 --- a/src/win/native/UiApplication.cpp +++ b/src/win/native/UiApplication.cpp @@ -100,15 +100,13 @@ std::vector WinUiApplication::GetAllWindow() { return result; } -std::shared_ptr WinUiApplication::CreateWindow( - INativeWindow* parent) { +INativeWindow* WinUiApplication::CreateWindow(INativeWindow* parent) { WinNativeWindow* p = nullptr; if (parent != nullptr) { p = CheckPlatform(parent, GetPlatformId()); } - return (new WinNativeWindow(this, window_manager_->GetGeneralWindowClass(), - WS_OVERLAPPEDWINDOW, p)) - ->GetResolver(); + return new WinNativeWindow(this, window_manager_->GetGeneralWindowClass(), + WS_OVERLAPPEDWINDOW, p); } cru::platform::graph::IGraphFactory* WinUiApplication::GetGraphFactory() { diff --git a/src/win/native/Window.cpp b/src/win/native/Window.cpp index 735221ca..d9237c4f 100644 --- a/src/win/native/Window.cpp +++ b/src/win/native/Window.cpp @@ -3,23 +3,24 @@ #include "WindowManager.hpp" #include "cru/common/Logger.hpp" #include "cru/platform/Check.hpp" +#include "cru/platform/native/Base.hpp" #include "cru/win/graph/direct/WindowPainter.hpp" #include "cru/win/native/Cursor.hpp" #include "cru/win/native/Exception.hpp" +#include "cru/win/native/InputMethod.hpp" #include "cru/win/native/Keyboard.hpp" #include "cru/win/native/UiApplication.hpp" #include "cru/win/native/WindowClass.hpp" #include #include +#include namespace cru::platform::native::win { WinNativeWindow::WinNativeWindow(WinUiApplication* application, WindowClass* window_class, DWORD window_style, WinNativeWindow* parent) - : application_(application), - resolver_(std::make_shared(this)), - parent_window_(parent) { + : application_(application), parent_window_(parent) { Expects(application); // application can't be null. if (parent != nullptr) { @@ -52,6 +53,8 @@ WinNativeWindow::WinNativeWindow(WinUiApplication* application, std::make_unique( application->GetDirectFactory(), hwnd_); window_render_target_->SetDpi(dpi_, dpi_); + + input_method_context_ = std::make_unique(this); } WinNativeWindow::~WinNativeWindow() { @@ -59,7 +62,6 @@ WinNativeWindow::~WinNativeWindow() { sync_flag_ = true; Close(); } - resolver_->Reset(); } void WinNativeWindow::Close() { ::DestroyWindow(hwnd_); } @@ -197,6 +199,10 @@ void WinNativeWindow::SetCursor(std::shared_ptr cursor) { } } +IInputMethodContext* WinNativeWindow::GetInputMethodContext() { + return static_cast(input_method_context_.get()); +} + bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param, LRESULT* result) { @@ -443,16 +449,4 @@ void WinNativeWindow::OnKeyUpInternal(int virtual_code) { void WinNativeWindow::OnActivatedInternal() {} void WinNativeWindow::OnDeactivatedInternal() {} - -void WinNativeWindowResolver::Reset() { - Expects(window_); // already reset, can't reset again - window_ = nullptr; -} - -WinNativeWindow* Resolve(gsl::not_null resolver) { - const auto window = resolver->Resolve(); - return window == nullptr ? nullptr - : CheckPlatform( - window, WinNativeResource::k_platform_id); -} // namespace cru::platform::native::win } // namespace cru::platform::native::win -- cgit v1.2.3