From 494d2db1c1203acc9d9f2b127b75c6df6160057a Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 19 Apr 2020 19:54:44 +0800 Subject: ... --- CMakeLists.txt | 1 + demos/CMakeLists.txt | 8 ++++ demos/input_method/CMakeLists.txt | 2 + demos/input_method/main.cpp | 0 demos/main/CMakeLists.txt | 2 + demos/main/main.cpp | 58 ++++++++++++++++++++++++++++ include/cru/platform/graph_base.hpp | 2 +- include/cru/platform/native/input_method.hpp | 2 +- include/cru/win/native/input_method.hpp | 2 +- src/CMakeLists.txt | 6 --- src/main.cpp | 58 ---------------------------- src/win/native/input_method.cpp | 44 ++++++++++++++++++--- 12 files changed, 112 insertions(+), 73 deletions(-) create mode 100644 demos/CMakeLists.txt create mode 100644 demos/input_method/CMakeLists.txt create mode 100644 demos/input_method/main.cpp create mode 100644 demos/main/CMakeLists.txt create mode 100644 demos/main/main.cpp delete mode 100644 src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 34adff17..4f82fa08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,3 +15,4 @@ set(CRU_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include) add_subdirectory(src) add_subdirectory(test) +add_subdirectory(demos) diff --git a/demos/CMakeLists.txt b/demos/CMakeLists.txt new file mode 100644 index 00000000..64612bf9 --- /dev/null +++ b/demos/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(cru_demo_base INTERFACE) + +if(WIN32) + target_link_libraries(cru_demo_base INTERFACE cru_win_native) +endif() + +add_subdirectory(main) +add_subdirectory(input_method) diff --git a/demos/input_method/CMakeLists.txt b/demos/input_method/CMakeLists.txt new file mode 100644 index 00000000..98e36e29 --- /dev/null +++ b/demos/input_method/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(demo_input_method main.cpp) +target_link_libraries(demo_input_method PRIVATE cru_demo_base) diff --git a/demos/input_method/main.cpp b/demos/input_method/main.cpp new file mode 100644 index 00000000..e69de29b diff --git a/demos/main/CMakeLists.txt b/demos/main/CMakeLists.txt new file mode 100644 index 00000000..9974671d --- /dev/null +++ b/demos/main/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(demo_main main.cpp) +target_link_libraries(demo_main PRIVATE cru_demo_base cru_ui) diff --git a/demos/main/main.cpp b/demos/main/main.cpp new file mode 100644 index 00000000..0172838e --- /dev/null +++ b/demos/main/main.cpp @@ -0,0 +1,58 @@ +#include "cru/platform/heap_debug.hpp" +#include "cru/platform/native/window.hpp" +#include "cru/ui/controls/button.hpp" +#include "cru/ui/controls/flex_layout.hpp" +#include "cru/ui/controls/stack_layout.hpp" +#include "cru/ui/controls/text_block.hpp" +#include "cru/ui/ui_host.hpp" +#include "cru/ui/window.hpp" +#include "cru/win/native/ui_application.hpp" + +using cru::platform::native::win::WinUiApplication; +using cru::ui::Rect; +using cru::ui::Thickness; +using cru::ui::Window; +using cru::ui::controls::Button; +using cru::ui::controls::FlexLayout; +using cru::ui::controls::StackLayout; +using cru::ui::controls::TextBlock; + +int main() { +#ifdef CRU_DEBUG + cru::platform::SetupHeapDebug(); +#endif + + std::unique_ptr application = + std::make_unique(); + + const auto window = Window::CreateOverlapped(); + + const auto flex_layout = FlexLayout::Create(); + + window->SetChild(flex_layout); + + const auto button = Button::Create(); + const auto text_block1 = TextBlock::Create(); + text_block1->SetText("Hello World!"); + button->SetChild(text_block1); + flex_layout->AddChild(button, 0); + + const auto text_block2 = TextBlock::Create(); + text_block2->SetText("Hello World!"); + + const auto text_block3 = TextBlock::Create(); + text_block3->SetText("Overlapped text"); + + const auto stack_layout = StackLayout::Create(); + stack_layout->AddChild(text_block2, 0); + stack_layout->AddChild(text_block3, 1); + flex_layout->AddChild(stack_layout, 1); + + const auto text_block4 = TextBlock::Create(); + text_block4->SetText("Hello World!!!"); + flex_layout->AddChild(text_block4, 2); + + window->GetUiHost()->GetNativeWindowResolver()->Resolve()->SetVisible(true); + + return application->Run(); +} diff --git a/include/cru/platform/graph_base.hpp b/include/cru/platform/graph_base.hpp index 98ac3993..f25a7baf 100644 --- a/include/cru/platform/graph_base.hpp +++ b/include/cru/platform/graph_base.hpp @@ -219,7 +219,7 @@ struct TextRange final { } constexpr TextRange() = default; - constexpr TextRange(const gsl::index position, const gsl::index count) + constexpr TextRange(const gsl::index position, const gsl::index count = 0) : position(position), count(count) {} gsl::index GetEnd() const { return position + count; } diff --git a/include/cru/platform/native/input_method.hpp b/include/cru/platform/native/input_method.hpp index 56e2fb27..48895f84 100644 --- a/include/cru/platform/native/input_method.hpp +++ b/include/cru/platform/native/input_method.hpp @@ -34,7 +34,7 @@ struct IInputMethodContext : virtual INativeResource { virtual void CancelComposition() = 0; - virtual const CompositionText& GetCompositionText() = 0; + virtual CompositionText GetCompositionText() = 0; // Set the candidate window lefttop. Use this method to prepare typing. virtual void SetCandidateWindowPosition(const Point& point) = 0; diff --git a/include/cru/win/native/input_method.hpp b/include/cru/win/native/input_method.hpp index 56e678a9..566eada2 100644 --- a/include/cru/win/native/input_method.hpp +++ b/include/cru/win/native/input_method.hpp @@ -51,7 +51,7 @@ class WinInputMethodContext : public WinNativeResource, void CancelComposition() override; - const CompositionText& GetCompositionText() override; + CompositionText GetCompositionText() override; void SetCandidateWindowPosition(const Point& point) override; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e2eb921c..e10aafbd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,9 +8,3 @@ endif() add_subdirectory(ui) -add_executable(demo main.cpp) -target_link_libraries(demo PRIVATE cru_ui) - -if(WIN32) - target_link_libraries(demo PRIVATE cru_win_native) -endif() diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index 0172838e..00000000 --- a/src/main.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "cru/platform/heap_debug.hpp" -#include "cru/platform/native/window.hpp" -#include "cru/ui/controls/button.hpp" -#include "cru/ui/controls/flex_layout.hpp" -#include "cru/ui/controls/stack_layout.hpp" -#include "cru/ui/controls/text_block.hpp" -#include "cru/ui/ui_host.hpp" -#include "cru/ui/window.hpp" -#include "cru/win/native/ui_application.hpp" - -using cru::platform::native::win::WinUiApplication; -using cru::ui::Rect; -using cru::ui::Thickness; -using cru::ui::Window; -using cru::ui::controls::Button; -using cru::ui::controls::FlexLayout; -using cru::ui::controls::StackLayout; -using cru::ui::controls::TextBlock; - -int main() { -#ifdef CRU_DEBUG - cru::platform::SetupHeapDebug(); -#endif - - std::unique_ptr application = - std::make_unique(); - - const auto window = Window::CreateOverlapped(); - - const auto flex_layout = FlexLayout::Create(); - - window->SetChild(flex_layout); - - const auto button = Button::Create(); - const auto text_block1 = TextBlock::Create(); - text_block1->SetText("Hello World!"); - button->SetChild(text_block1); - flex_layout->AddChild(button, 0); - - const auto text_block2 = TextBlock::Create(); - text_block2->SetText("Hello World!"); - - const auto text_block3 = TextBlock::Create(); - text_block3->SetText("Overlapped text"); - - const auto stack_layout = StackLayout::Create(); - stack_layout->AddChild(text_block2, 0); - stack_layout->AddChild(text_block3, 1); - flex_layout->AddChild(stack_layout, 1); - - const auto text_block4 = TextBlock::Create(); - text_block4->SetText("Hello World!!!"); - flex_layout->AddChild(text_block4, 2); - - window->GetUiHost()->GetNativeWindowResolver()->Resolve()->SetVisible(true); - - return application->Run(); -} diff --git a/src/win/native/input_method.cpp b/src/win/native/input_method.cpp index dace5827..73831bd5 100644 --- a/src/win/native/input_method.cpp +++ b/src/win/native/input_method.cpp @@ -128,9 +128,17 @@ CompositionText GetCompositionInfo(HIMC imm_context) { auto clauses = GetCompositionClauses(imm_context, w_target_start, w_target_end); - int cursor = ::ImmGetCompositionString(imm_context, GCS_CURSORPOS, NULL, 0); + int w_cursor = ::ImmGetCompositionString(imm_context, GCS_CURSORPOS, NULL, 0); - // TODO: Finish this. + auto text = platform::win::ToUtf8String(w_text); + for (auto& clause : clauses) { + clause.start = platform::win::IndexUtf16ToUtf8(w_text, clause.start, text); + clause.end = platform::win::IndexUtf16ToUtf8(w_text, clause.end, text); + } + int cursor = platform::win::IndexUtf16ToUtf8(w_text, w_cursor, text); + + return CompositionText{std::move(text), std::move(clauses), + TextRange{cursor}}; } } // namespace @@ -161,21 +169,45 @@ void WinInputMethodContext::DisableIME() { if (native_window == nullptr) return; const auto hwnd = native_window->GetWindowHandle(); + AutoHIMC himc{hwnd}; + + if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_COMPLETE, 0)) { + log::Warn( + "WinInputMethodContext: Failed to complete composition before disable " + "ime."); + } + if (::ImmAssociateContextEx(hwnd, nullptr, 0) == FALSE) { log::Warn("WinInputMethodContext: Failed to disable ime."); } } void WinInputMethodContext::CompleteComposition() { - // TODO: Not implemented. + auto optional_himc = TryGetHIMC(); + if (!optional_himc.has_value()) return; + auto himc = *std::move(optional_himc); + + if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_COMPLETE, 0)) { + log::Warn("WinInputMethodContext: Failed to complete composition."); + } } void WinInputMethodContext::CancelComposition() { - // TODO: Not implemented. + auto optional_himc = TryGetHIMC(); + if (!optional_himc.has_value()) return; + auto himc = *std::move(optional_himc); + + if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_CANCEL, 0)) { + log::Warn("WinInputMethodContext: Failed to complete composition."); + } } -const CompositionText& WinInputMethodContext::GetCompositionText() { - // TODO: Not implemented. +CompositionText WinInputMethodContext::GetCompositionText() { + auto optional_himc = TryGetHIMC(); + if (!optional_himc.has_value()) return CompositionText{}; + auto himc = *std::move(optional_himc); + + return GetCompositionInfo(himc.Get()); } void WinInputMethodContext::SetCandidateWindowPosition(const Point& point) { -- cgit v1.2.3