diff options
author | crupest <crupest@outlook.com> | 2020-04-05 00:04:05 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-04-05 00:04:05 +0800 |
commit | 37bb421e963662e8203acbe3a03bdbd5d1f5858e (patch) | |
tree | 400af7a9d378be209158eda8ca8adeced60b0cc8 | |
parent | ee61633d81cc9e34c3bd8b5fbfb6a5a25a1f3ea5 (diff) | |
download | cru-37bb421e963662e8203acbe3a03bdbd5d1f5858e.tar.gz cru-37bb421e963662e8203acbe3a03bdbd5d1f5858e.tar.bz2 cru-37bb421e963662e8203acbe3a03bdbd5d1f5858e.zip |
...
-rw-r--r-- | include/cru/platform/native/input_method.hpp | 13 | ||||
-rw-r--r-- | include/cru/win/native/input_method.hpp | 19 | ||||
-rw-r--r-- | include/cru/win/native/window_native_message_event_args.hpp | 4 | ||||
-rw-r--r-- | src/win/native/input_method.cpp | 43 | ||||
-rw-r--r-- | src/win/native/window_manager.cpp | 4 |
5 files changed, 68 insertions, 15 deletions
diff --git a/include/cru/platform/native/input_method.hpp b/include/cru/platform/native/input_method.hpp index ecc47fd8..6ca85852 100644 --- a/include/cru/platform/native/input_method.hpp +++ b/include/cru/platform/native/input_method.hpp @@ -9,17 +9,22 @@ namespace cru::platform::native { // It is a reference, so there is a ref count, remember to destroy it to release // the ref after use. struct IInputMethodContextRef : INativeResource { + // Return true if you should draw composition text manually. Return false if + // system will take care of that for you. + virtual bool ShouldManuallyDrawCompositionText() = 0; // Reset composition string. Use this method to prepare typing. virtual void Reset() = 0; // Get the composition string. - virtual std::string GetCompositionString() = 0; + virtual std::string GetCompositionText() = 0; // Set the candidate window lefttop. Use this method to prepare typing. virtual void SetCandidateWindowPosition(const Point& point); - // Triggered every time composition text changes, evet args is the new + // Triggered when user starts composition. + virtual IEvent<std::nullptr_t>* CompositionStartEvent() = 0; + // Triggered when user stops composition. + virtual IEvent<std::nullptr_t>* CompositionEndEvent() = 0; + // Triggered every time composition text changes, event args is the new // composition text. virtual IEvent<std::string>* CompositionTextChangeEvent() = 0; - // User comfirmed compostition. Use this method to get the final input text. - virtual IEvent<std::string>* CharEvent() = 0; }; struct IInputMethodManager : INativeResource { diff --git a/include/cru/win/native/input_method.hpp b/include/cru/win/native/input_method.hpp index 3ea16709..2e09aac4 100644 --- a/include/cru/win/native/input_method.hpp +++ b/include/cru/win/native/input_method.hpp @@ -2,6 +2,7 @@ #include "resource.hpp" #include "cru/platform/native/input_method.hpp" +#include "window_native_message_event_args.hpp" #include <imm.h> @@ -20,23 +21,33 @@ class WinInputMethodContextRef : public WinNativeResource, ::HIMC GetHandle() const { return handle_; } + bool ShouldManuallyDrawCompositionText() override { return true; } + void Reset() override; - std::string GetCompositionString() override; + std::string GetCompositionText() override; void SetCandidateWindowPosition(const Point& point) override; + IEvent<std::nullptr_t>* CompositionStartEvent() override; + + IEvent<std::nullptr_t>* CompositionEndEvent() override; + IEvent<std::string>* CompositionTextChangeEvent() override; - IEvent<std::string>* CharEvent() override; + private: + void OnWindowNativeMessage(WindowNativeMessageEventArgs& args); private: - WinNativeWindow* window_; + [[maybe_unused]] WinNativeWindow* window_; + + std::vector<EventRevokerGuard> event_revoker_guards_; ::HWND window_handle_; ::HIMC handle_; + Event<std::nullptr_t> composition_start_event_; + Event<std::nullptr_t> composition_end_event_; Event<std::string> composition_text_change_event_; - Event<std::string> char_event_; }; } // namespace cru::platform::native::win diff --git a/include/cru/win/native/window_native_message_event_args.hpp b/include/cru/win/native/window_native_message_event_args.hpp index 18de1f46..f5476735 100644 --- a/include/cru/win/native/window_native_message_event_args.hpp +++ b/include/cru/win/native/window_native_message_event_args.hpp @@ -19,7 +19,7 @@ class WindowNativeMessageEventArgs : public Object { CRU_DEFAULT_MOVE(WindowNativeMessageEventArgs) ~WindowNativeMessageEventArgs() override = default; - WindowNativeMessage GetWindowMessage() const { return message_; } + const WindowNativeMessage& GetWindowMessage() const { return message_; } LRESULT GetResult() const { return result_; } void SetResult(LRESULT result) { result_ = result; } @@ -27,7 +27,7 @@ class WindowNativeMessageEventArgs : public Object { bool IsHandled() const { return handled_; } void SetHandled(bool handled) { handled_ = handled; } - void HandledAndSetResult(LRESULT result) { + void HandleWithResult(LRESULT result) { handled_ = true; result_ = result; } diff --git a/src/win/native/input_method.cpp b/src/win/native/input_method.cpp index 4edfdc5f..837d0ed7 100644 --- a/src/win/native/input_method.cpp +++ b/src/win/native/input_method.cpp @@ -17,6 +17,11 @@ WinInputMethodContextRef::WinInputMethodContextRef(WinNativeWindow* window) handle_ = ::ImmGetContext(window_handle_); // TODO: Events + + event_revoker_guards_.push_back( + EventRevokerGuard(window->NativeMessageEvent()->AddHandler( + std::bind(&WinInputMethodContextRef::OnWindowNativeMessage, this, + std::placeholders::_1)))); } WinInputMethodContextRef::~WinInputMethodContextRef() { @@ -34,7 +39,7 @@ void WinInputMethodContextRef::Reset() { } } -std::string WinInputMethodContextRef::GetCompositionString() { +std::string WinInputMethodContextRef::GetCompositionText() { const auto length = ::ImmGetCompositionStringW(handle_, GCS_RESULTREADSTR, NULL, 0) + sizeof(wchar_t); @@ -65,11 +70,43 @@ void WinInputMethodContextRef::SetCandidateWindowPosition(const Point& point) { "position."); } +IEvent<std::nullptr_t>* WinInputMethodContextRef::CompositionStartEvent() { + return &composition_start_event_; +} + +IEvent<std::nullptr_t>* WinInputMethodContextRef::CompositionEndEvent() { + return &composition_end_event_; +}; + IEvent<std::string>* WinInputMethodContextRef::CompositionTextChangeEvent() { return &composition_text_change_event_; } -IEvent<std::string>* WinInputMethodContextRef::CharEvent() { - return &char_event_; +void WinInputMethodContextRef::OnWindowNativeMessage( + WindowNativeMessageEventArgs& args) { + const auto message = args.GetWindowMessage(); + switch (message.msg) { + case WM_IME_COMPOSITION: { + composition_text_change_event_.Raise(this->GetCompositionText()); + args.HandleWithResult(0); + break; + } + case WM_IME_STARTCOMPOSITION: { + composition_start_event_.Raise(nullptr); + args.HandleWithResult(0); + break; + } + case WM_IME_ENDCOMPOSITION: { + composition_end_event_.Raise(nullptr); + args.HandleWithResult(0); + break; + } + case WM_IME_SETCONTEXT: { + const auto new_l_param = + message.l_param & (~static_cast<LPARAM>(ISC_SHOWUICOMPOSITIONWINDOW)); + args.HandleWithResult(::DefWindowProcW(message.hwnd, message.msg, + message.w_param, new_l_param)); + } + } } } // namespace cru::platform::native::win diff --git a/src/win/native/window_manager.cpp b/src/win/native/window_manager.cpp index e1b14f4b..205a139c 100644 --- a/src/win/native/window_manager.cpp +++ b/src/win/native/window_manager.cpp @@ -25,7 +25,7 @@ WindowManager::WindowManager(WinUiApplication* application) { } WindowManager::~WindowManager() { - for (const auto [key, window] : window_map_) delete window; + for (const auto& [key, window] : window_map_) delete window; } void WindowManager::RegisterWindow(HWND hwnd, WinNativeWindow* window) { @@ -50,7 +50,7 @@ WinNativeWindow* WindowManager::FromHandle(HWND hwnd) { std::vector<WinNativeWindow*> WindowManager::GetAllWindows() const { std::vector<WinNativeWindow*> windows; - for (auto [key, value] : window_map_) windows.push_back(value); + for (const auto& [key, value] : window_map_) windows.push_back(value); return windows; } } // namespace cru::platform::native::win |