aboutsummaryrefslogtreecommitdiff
path: root/demos/InputMethod/main.cpp
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2023-10-18 22:55:18 +0800
committercrupest <crupest@outlook.com>2023-10-18 22:55:18 +0800
commite8abfdb0c1d3e918bfaac2077cc7e5332c1cfaf9 (patch)
tree9f90a0ca3d49cb33ba9ad28568d5e400ceeffce7 /demos/InputMethod/main.cpp
parent0a67b1c862954d0d18d4fbf322c31ea0faf065d7 (diff)
downloadcru-e8abfdb0c1d3e918bfaac2077cc7e5332c1cfaf9.tar.gz
cru-e8abfdb0c1d3e918bfaac2077cc7e5332c1cfaf9.tar.bz2
cru-e8abfdb0c1d3e918bfaac2077cc7e5332c1cfaf9.zip
Fix input method bugs on macos.
There are a lot of problems about input methods and we will definitely spend more on this. And the bug made me awkward on today's interview when showing the demo.
Diffstat (limited to 'demos/InputMethod/main.cpp')
-rw-r--r--demos/InputMethod/main.cpp98
1 files changed, 58 insertions, 40 deletions
diff --git a/demos/InputMethod/main.cpp b/demos/InputMethod/main.cpp
index abbbed2c..fc63dd5e 100644
--- a/demos/InputMethod/main.cpp
+++ b/demos/InputMethod/main.cpp
@@ -1,4 +1,5 @@
#include "cru/platform/Color.h"
+#include "cru/platform/GraphicsBase.h"
#include "cru/platform/bootstrap/Bootstrap.h"
#include "cru/platform/graphics/Factory.h"
#include "cru/platform/graphics/Font.h"
@@ -7,12 +8,20 @@
#include "cru/platform/gui/UiApplication.h"
#include "cru/platform/gui/Window.h"
-int main() {
- using namespace cru;
- using namespace cru::platform;
- using namespace cru::platform::graphics;
- using namespace cru::platform::gui;
+#include <optional>
+
+using namespace cru;
+using namespace cru::platform;
+using namespace cru::platform::graphics;
+using namespace cru::platform::gui;
+
+struct InputMethodState {
+ CompositionText composition_text;
+ Rect cursor_rect;
+ TextRange colored_text_range;
+};
+int main() {
IUiApplication* application = bootstrap::CreateUiApplication();
auto graphics_factory = application->GetGraphicsFactory();
@@ -33,22 +42,30 @@ int main() {
std::shared_ptr<IFont> font = graphics_factory->CreateFont(String{}, 30);
- float window_width = 10000;
-
auto prompt_text_layout =
graphics_factory->CreateTextLayout(font,
u"Ctrl+1: Enable IME\n"
u"Ctrl+2: Disable IME\n"
u"Ctrl+3: Complete composition.\n"
u"Ctrl+4: Cancel composition.");
+ float anchor_y;
- std::optional<CompositionText> optional_composition_text;
String committed_text;
+ auto text_layout = graphics_factory->CreateTextLayout(font, u"");
+ std::optional<InputMethodState> state;
+
+ auto update_text_layout_width = [&prompt_text_layout, &anchor_y,
+ &text_layout](float width) {
+ prompt_text_layout->SetMaxWidth(width);
+ text_layout->SetMaxWidth(width);
+ anchor_y = prompt_text_layout->GetTextBounds().height;
+ };
+
+ update_text_layout_width(window->GetClientSize().width);
window->ResizeEvent()->AddHandler(
- [&prompt_text_layout, &window_width](const Size& size) {
- prompt_text_layout->SetMaxWidth(size.width);
- window_width = size.width;
+ [&update_text_layout_width](const Size& size) {
+ update_text_layout_width(size.width);
});
window->PaintEvent()->AddHandler([&](auto) {
@@ -57,16 +74,8 @@ int main() {
painter->DrawText(Point{}, prompt_text_layout.get(), brush.get());
- const auto anchor_y = prompt_text_layout->GetTextBounds().height;
-
- auto text_layout = graphics_factory->CreateTextLayout(
- font, committed_text + (optional_composition_text
- ? optional_composition_text->text
- : u""));
- text_layout->SetMaxWidth(window_width);
-
- if (optional_composition_text) {
- const auto& composition_text = *optional_composition_text;
+ if (state) {
+ const auto& composition_text = state->composition_text;
for (int i = 0; i < static_cast<int>(composition_text.clauses.size());
i++) {
@@ -85,19 +94,13 @@ int main() {
painter->DrawText(Point{0, anchor_y}, text_layout.get(), brush.get());
- if (optional_composition_text) {
- const auto& composition_text = *optional_composition_text;
+ if (state) {
+ const auto& composition_text = state->composition_text;
+ const auto& cursor_rect = state->cursor_rect;
- const auto cursor_pos = composition_text.selection.position +
- gsl::narrow_cast<int>(committed_text.size());
-
- const auto cursor_lefttop =
- text_layout->TextSinglePoint(cursor_pos, false);
-
- painter->FillRectangle(
- Rect{cursor_lefttop.left, cursor_lefttop.top + anchor_y, 3,
- cursor_lefttop.height},
- brush.get());
+ painter->FillRectangle(Rect{cursor_rect.left, cursor_rect.top + anchor_y,
+ 3, cursor_rect.height},
+ brush.get());
}
painter->EndDraw();
@@ -131,15 +134,30 @@ int main() {
window->RequestRepaint();
});
- input_method_context->CompositionEvent()->AddHandler(
- [window, &input_method_context, &optional_composition_text](auto) {
- optional_composition_text = input_method_context->GetCompositionText();
- window->RequestRepaint();
- });
+ input_method_context->CompositionEvent()->AddHandler([window,
+ &input_method_context,
+ &committed_text,
+ &anchor_y, &state,
+ &text_layout](auto) {
+ const auto composition_text = input_method_context->GetCompositionText();
+ state.emplace();
+ state->composition_text = input_method_context->GetCompositionText();
+
+ text_layout->SetText(committed_text + composition_text.text);
+
+ const auto cursor_pos = composition_text.selection.position +
+ gsl::narrow_cast<int>(committed_text.size());
+ state->cursor_rect = text_layout->TextSinglePoint(cursor_pos, false);
+
+ input_method_context->SetCandidateWindowPosition(
+ {state->cursor_rect.left, anchor_y + state->cursor_rect.GetBottom()});
+
+ window->RequestRepaint();
+ });
input_method_context->CompositionEndEvent()->AddHandler(
- [window, &optional_composition_text](auto) {
- optional_composition_text = std::nullopt;
+ [window, &state](auto) {
+ state = std::nullopt;
window->RequestRepaint();
});