From 95b0de041024454a5ae53ee61326231687a26582 Mon Sep 17 00:00:00 2001 From: Seungsoo Lee Date: Mon, 22 Mar 2021 15:28:21 +0900 Subject: [PATCH] Update TextInputChannel to supprot platform view (#52) * Current the text input channel handles user input for only existing flutter components. Therefore, we added the logic so that the platform view can also handle the composition events happened by user input. --- .../tizen/channels/platform_view_channel.cc | 17 ++++ .../tizen/channels/platform_view_channel.h | 3 + .../tizen/channels/text_input_channel.cc | 93 +++++++++++++++---- .../tizen/channels/text_input_channel.h | 4 + shell/platform/tizen/key_event_handler.cc | 3 - .../tizen/public/flutter_platform_view.h | 2 + 6 files changed, 102 insertions(+), 20 deletions(-) diff --git a/shell/platform/tizen/channels/platform_view_channel.cc b/shell/platform/tizen/channels/platform_view_channel.cc index 53d29aa1483b7..0cd0825ca0b07 100644 --- a/shell/platform/tizen/channels/platform_view_channel.cc +++ b/shell/platform/tizen/channels/platform_view_channel.cc @@ -108,6 +108,23 @@ void PlatformViewChannel::SendKeyEvent(Ecore_Event_Key* key, bool is_down) { } } +void PlatformViewChannel::DispatchCompositionUpdateEvent( + const std::string& key) { + auto instances = ViewInstances(); + auto it = instances.find(CurrentFocusedViewId()); + if (it != instances.end()) { + it->second->DispatchCompositionUpdateEvent(key.c_str(), key.size()); + } +} + +void PlatformViewChannel::DispatchCompositionEndEvent(const std::string& key) { + auto instances = ViewInstances(); + auto it = instances.find(CurrentFocusedViewId()); + if (it != instances.end()) { + it->second->DispatchCompositionEndEvent(key.c_str(), key.size()); + } +} + int PlatformViewChannel::CurrentFocusedViewId() { for (auto it = view_instances_.begin(); it != view_instances_.end(); it++) { if (it->second->IsFocused()) { diff --git a/shell/platform/tizen/channels/platform_view_channel.h b/shell/platform/tizen/channels/platform_view_channel.h index bb8f9494e87e4..84e3c5ce91fbd 100644 --- a/shell/platform/tizen/channels/platform_view_channel.h +++ b/shell/platform/tizen/channels/platform_view_channel.h @@ -30,6 +30,9 @@ class PlatformViewChannel { void SendKeyEvent(Ecore_Event_Key* key, bool is_down); int CurrentFocusedViewId(); + void DispatchCompositionUpdateEvent(const std::string& key); + void DispatchCompositionEndEvent(const std::string& key); + private: TizenEmbedderEngine* engine_; std::unique_ptr> channel_; diff --git a/shell/platform/tizen/channels/text_input_channel.cc b/shell/platform/tizen/channels/text_input_channel.cc index 6aa7bf1f53f4b..71cf840326b35 100644 --- a/shell/platform/tizen/channels/text_input_channel.cc +++ b/shell/platform/tizen/channels/text_input_channel.cc @@ -59,19 +59,37 @@ static bool IsASCIIPrintableKey(char c) { void TextInputChannel::CommitCallback(void* data, Ecore_IMF_Context* ctx, void* event_info) { TextInputChannel* self = (TextInputChannel*)data; + if (!self) { + return; + } char* str = (char*)event_info; + if (self->engine_ && self->engine_->platform_view_channel && + self->engine_->platform_view_channel->CurrentFocusedViewId() > -1) { + self->engine_->platform_view_channel->DispatchCompositionEndEvent(str); + return; + } + self->OnCommit(str); } void TextInputChannel::PreeditCallback(void* data, Ecore_IMF_Context* ctx, void* event_info) { TextInputChannel* self = (TextInputChannel*)data; - char* preedit_string = nullptr; + if (!self) { + return; + } + + char* str = nullptr; int cursor_pos; - ecore_imf_context_preedit_string_get(ctx, &preedit_string, &cursor_pos); - if (preedit_string) { - self->OnPreedit(preedit_string, cursor_pos); - free(preedit_string); + ecore_imf_context_preedit_string_get(ctx, &str, &cursor_pos); + if (str) { + if (self->engine_ && self->engine_->platform_view_channel && + self->engine_->platform_view_channel->CurrentFocusedViewId() > -1) { + self->OnPreeditForPlatformView(str, cursor_pos); + } else { + self->OnPreedit(str, cursor_pos); + } + free(str); } } @@ -99,6 +117,7 @@ void TextInputChannel::InputPanelStateChangedCallback( TextInputChannel* self = (TextInputChannel*)data; switch (value) { case ECORE_IMF_INPUT_PANEL_STATE_SHOW: + self->SetSoftwareKeyboardShowing(); break; case ECORE_IMF_INPUT_PANEL_STATE_HIDE: self->HideSoftwareKeyboard(); // FIXME: Fallback for HW back-key @@ -275,7 +294,7 @@ TextInputChannel::~TextInputChannel() { } void TextInputChannel::OnKeyDown(Ecore_Event_Key* key) { - if (active_model_ && !FilterEvent(key) && !have_preedit_) { + if (!FilterEvent(key) && !have_preedit_) { NonIMFFallback(key); } } @@ -431,6 +450,8 @@ bool TextInputChannel::FilterEvent(Ecore_Event_Key* keyDownEvent) { if (isIME) { if (!strcmp(keyDownEvent->key, "Left") || !strcmp(keyDownEvent->key, "Right") || + !strcmp(keyDownEvent->key, "Up") || + !strcmp(keyDownEvent->key, "Down") || !strcmp(keyDownEvent->key, "End") || !strcmp(keyDownEvent->key, "Home") || !strcmp(keyDownEvent->key, "BackSpace") || @@ -481,35 +502,49 @@ void TextInputChannel::NonIMFFallback(Ecore_Event_Key* keyDownEvent) { } bool select = !strcmp(keyDownEvent->key, "Select"); + bool is_filtered = true; if (!strcmp(keyDownEvent->key, "Left")) { - if (active_model_->MoveCursorBack()) { + if (active_model_ && active_model_->MoveCursorBack()) { SendStateUpdate(*active_model_); } } else if (!strcmp(keyDownEvent->key, "Right")) { - if (active_model_->MoveCursorForward()) { + if (active_model_ && active_model_->MoveCursorForward()) { SendStateUpdate(*active_model_); } } else if (!strcmp(keyDownEvent->key, "End")) { - active_model_->MoveCursorToEnd(); - SendStateUpdate(*active_model_); + if (active_model_) { + active_model_->MoveCursorToEnd(); + SendStateUpdate(*active_model_); + } } else if (!strcmp(keyDownEvent->key, "Home")) { - active_model_->MoveCursorToBeginning(); - SendStateUpdate(*active_model_); + if (active_model_) { + active_model_->MoveCursorToBeginning(); + SendStateUpdate(*active_model_); + } } else if (!strcmp(keyDownEvent->key, "BackSpace")) { - if (active_model_->Backspace()) { + if (active_model_ && active_model_->Backspace()) { SendStateUpdate(*active_model_); } } else if (!strcmp(keyDownEvent->key, "Delete")) { - if (active_model_->Delete()) { + if (active_model_ && active_model_->Delete()) { SendStateUpdate(*active_model_); } } else if (!strcmp(keyDownEvent->key, "Return") || (select && !in_select_mode_)) { - EnterPressed(active_model_.get(), select); + if (active_model_) { + EnterPressed(active_model_.get(), select); + } } else if (keyDownEvent->string && strlen(keyDownEvent->string) == 1 && IsASCIIPrintableKey(keyDownEvent->string[0])) { - active_model_->AddCodePoint(keyDownEvent->string[0]); - SendStateUpdate(*active_model_); + if (active_model_) { + active_model_->AddCodePoint(keyDownEvent->string[0]); + SendStateUpdate(*active_model_); + } + } else { + is_filtered = false; + } + if (!active_model_ && is_filtered) { + engine_->platform_view_channel->SendKeyEvent(keyDownEvent, true); } SetEditStatus(EditStatus::kNone); } @@ -570,6 +605,30 @@ void TextInputChannel::OnPreedit(std::string str, int cursor_pos) { preedit_end_pos_); } } +void TextInputChannel::OnPreeditForPlatformView(std::string str, + int cursor_pos) { + FT_LOGD("OnPreeditForPlatformView str[%s], cursor_pos[%d]", str.data(), + cursor_pos); + + SetEditStatus(EditStatus::kPreeditStart); + if (str.compare("") == 0) { + SetEditStatus(EditStatus::kPreeditEnd); + } + + if (edit_status_ == EditStatus::kPreeditStart || + (edit_status_ == EditStatus::kPreeditEnd && + // For tv, fix me + last_handled_ecore_event_keyname_.compare("Return") != 0)) { + FT_LOGD("last_handled_ecore_event_keyname_[%s]", + last_handled_ecore_event_keyname_.data()); + last_handled_ecore_event_keyname_ = ""; + } + + have_preedit_ = false; + if (edit_status_ == EditStatus::kPreeditStart) { + engine_->platform_view_channel->DispatchCompositionUpdateEvent(str); + } +} void TextInputChannel::ShowSoftwareKeyboard() { FT_LOGD("Show input panel"); diff --git a/shell/platform/tizen/channels/text_input_channel.h b/shell/platform/tizen/channels/text_input_channel.h index ee3d01d01291c..74b6629975a0b 100644 --- a/shell/platform/tizen/channels/text_input_channel.h +++ b/shell/platform/tizen/channels/text_input_channel.h @@ -29,9 +29,13 @@ class TextInputChannel { void OnKeyDown(Ecore_Event_Key* key); void OnCommit(std::string str); void OnPreedit(std::string str, int cursor_pos); + void OnPreeditForPlatformView(std::string str, int cursor_pos); + void ShowSoftwareKeyboard(); void HideSoftwareKeyboard(); bool IsSoftwareKeyboardShowing() { return is_software_keyboard_showing_; } + void SetSoftwareKeyboardShowing() { is_software_keyboard_showing_ = true; } + void SetEditStatus(EditStatus edit_status); SoftwareKeyboardGeometry GetCurrentKeyboardGeometry() { return current_keyboard_geometry_; diff --git a/shell/platform/tizen/key_event_handler.cc b/shell/platform/tizen/key_event_handler.cc index aab40b1c22906..28f7d8d687200 100644 --- a/shell/platform/tizen/key_event_handler.cc +++ b/shell/platform/tizen/key_event_handler.cc @@ -46,9 +46,6 @@ Eina_Bool KeyEventHandler::OnKey(void *data, int type, void *event) { if (engine->key_event_channel) { engine->key_event_channel->SendKeyEvent(key, is_down); } - if (engine->platform_view_channel) { - engine->platform_view_channel->SendKeyEvent(key, is_down); - } } return ECORE_CALLBACK_PASS_ON; } diff --git a/shell/platform/tizen/public/flutter_platform_view.h b/shell/platform/tizen/public/flutter_platform_view.h index 8a5ed9dd7fd46..4cc83dec46c5f 100644 --- a/shell/platform/tizen/public/flutter_platform_view.h +++ b/shell/platform/tizen/public/flutter_platform_view.h @@ -38,6 +38,8 @@ class PlatformView { // Key input event virtual void DispatchKeyDownEvent(Ecore_Event_Key* key) = 0; virtual void DispatchKeyUpEvent(Ecore_Event_Key* key) = 0; + virtual void DispatchCompositionUpdateEvent(const char* str, int size) = 0; + virtual void DispatchCompositionEndEvent(const char* str, int size) = 0; virtual void SetSoftwareKeyboardContext(Ecore_IMF_Context* context) = 0;