diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7bc2c8e5ae7b6..b252049297288 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,13 +41,6 @@ jobs: path: src/flutter fetch-depth: 0 - - uses: actions/cache@v2 - with: - path: src/out/${{ env.OUTPUT_NAME }} - key: out-build-${{ env.OUTPUT_NAME }}-${{ github.sha }} - restore-keys: | - out-build-${{ env.OUTPUT_NAME }}- - - name: gclient sync run: | src/flutter/ci/tizen/gclient-prepare-sync.sh --reduce-deps --shallow-sync @@ -202,13 +195,6 @@ jobs: with: path: src/flutter - - uses: actions/cache@v2 - with: - path: src/out/${{ env.OUTPUT_NAME }} - key: out-macos-build-${{ env.OUTPUT_NAME }}-${{ github.sha }} - restore-keys: | - out-macos-build-${{ env.OUTPUT_NAME }}- - - name: install depot_tools run: | git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git diff --git a/shell/platform/tizen/BUILD.gn b/shell/platform/tizen/BUILD.gn index 44574e346ac56..0100b97c15338 100644 --- a/shell/platform/tizen/BUILD.gn +++ b/shell/platform/tizen/BUILD.gn @@ -65,6 +65,8 @@ config("rootstrap_include_dirs") { "$custom_sysroot/usr/include/ecore-con-1", "$custom_sysroot/usr/include/ecore-evas-1", "$custom_sysroot/usr/include/ecore-file-1", + "$custom_sysroot/usr/include/ecore-imf-evas-1", + "$custom_sysroot/usr/include/ecore-input-evas-1", "$custom_sysroot/usr/include/edje-1", "$custom_sysroot/usr/include/eet-1", "$custom_sysroot/usr/include/efl-1/interfaces", @@ -150,6 +152,7 @@ template("embedder") { "dlog", "ecore", "ecore_imf", + "ecore_imf_evas", "ecore_input", "efl-extension", "eina", diff --git a/shell/platform/tizen/channels/key_event_channel.cc b/shell/platform/tizen/channels/key_event_channel.cc index 59c8a9a06ab63..041056338f743 100644 --- a/shell/platform/tizen/channels/key_event_channel.cc +++ b/shell/platform/tizen/channels/key_event_channel.cc @@ -254,11 +254,14 @@ KeyEventChannel::KeyEventChannel(BinaryMessenger* messenger) KeyEventChannel::~KeyEventChannel() {} -void KeyEventChannel::SendKeyEvent(Ecore_Event_Key* key, - bool is_down, - std::function callback) { - uint32_t scan_code = key->keycode; - auto iter1 = kSymbolToScanCode.find(key->key); +void KeyEventChannel::SendKey(const char* key, + const char* string, + const char* compose, + uint32_t modifiers, + uint32_t scan_code, + bool is_down, + std::function callback) { + auto iter1 = kSymbolToScanCode.find(key); if (iter1 != kSymbolToScanCode.end()) { scan_code = iter1->second; } @@ -269,16 +272,16 @@ void KeyEventChannel::SendKeyEvent(Ecore_Event_Key* key, key_code = iter2->second; } - int modifiers = 0; + int gtk_modifiers = 0; for (auto element : kEcoreModifierToGtkModifier) { - if (element.first & key->modifiers) { - modifiers |= element.second; + if (element.first & modifiers) { + gtk_modifiers |= element.second; } } uint32_t unicode_scalar_values = 0; - if (key->compose) { - unicode_scalar_values = Utf8ToUtf32CodePoint(key->compose); + if (compose) { + unicode_scalar_values = Utf8ToUtf32CodePoint(compose); } rapidjson::Document event(rapidjson::kObjectType); @@ -288,7 +291,7 @@ void KeyEventChannel::SendKeyEvent(Ecore_Event_Key* key, event.AddMember(kUnicodeScalarValuesKey, unicode_scalar_values, allocator); event.AddMember(kKeyCodeKey, key_code, allocator); event.AddMember(kScanCodeKey, scan_code, allocator); - event.AddMember(kModifiersKey, modifiers, allocator); + event.AddMember(kModifiersKey, gtk_modifiers, allocator); if (is_down) { event.AddMember(kTypeKey, kKeyDown, allocator); } else { diff --git a/shell/platform/tizen/channels/key_event_channel.h b/shell/platform/tizen/channels/key_event_channel.h index e70cbdfb707db..c22d8c2eb46fc 100644 --- a/shell/platform/tizen/channels/key_event_channel.h +++ b/shell/platform/tizen/channels/key_event_channel.h @@ -5,8 +5,6 @@ #ifndef EMBEDDER_KEY_EVENT_CHANNEL_H_ #define EMBEDDER_KEY_EVENT_CHANNEL_H_ -#include - #include #include "flutter/shell/platform/common/client_wrapper/include/flutter/basic_message_channel.h" @@ -20,9 +18,13 @@ class KeyEventChannel { explicit KeyEventChannel(BinaryMessenger* messenger); virtual ~KeyEventChannel(); - void SendKeyEvent(Ecore_Event_Key* event, - bool is_down, - std::function callback); + void SendKey(const char* key, + const char* string, + const char* compose, + uint32_t modifiers, + uint32_t scan_code, + bool is_down, + std::function callback); private: std::unique_ptr> channel_; diff --git a/shell/platform/tizen/channels/platform_view_channel.cc b/shell/platform/tizen/channels/platform_view_channel.cc index 2852760c56be6..e196d4198af15 100644 --- a/shell/platform/tizen/channels/platform_view_channel.cc +++ b/shell/platform/tizen/channels/platform_view_channel.cc @@ -79,14 +79,15 @@ void PlatformViewChannel::ClearViewFactories() { view_factories_.clear(); } -void PlatformViewChannel::SendKeyEvent(Ecore_Event_Key* event, bool is_down) { +void PlatformViewChannel::SendKey(const char* key, + const char* string, + const char* compose, + uint32_t modifiers, + uint32_t scan_code, + bool is_down) { PlatformView* view = FindFocusedView(); if (view) { - if (is_down) { - view->DispatchKeyDownEvent(event); - } else { - view->DispatchKeyUpEvent(event); - } + view->SendKey(key, string, compose, modifiers, scan_code, is_down); } } diff --git a/shell/platform/tizen/channels/platform_view_channel.h b/shell/platform/tizen/channels/platform_view_channel.h index 0ef3ef8b26fda..e847b4e18b92d 100644 --- a/shell/platform/tizen/channels/platform_view_channel.h +++ b/shell/platform/tizen/channels/platform_view_channel.h @@ -5,8 +5,6 @@ #ifndef EMBEDDER_PLATFORM_VIEW_CHANNEL_H_ #define EMBEDDER_PLATFORM_VIEW_CHANNEL_H_ -#include - #include #include #include @@ -30,7 +28,12 @@ class PlatformViewChannel { return view_factories_; } - void SendKeyEvent(Ecore_Event_Key* event, bool is_down); + void SendKey(const char* key, + const char* string, + const char* compose, + uint32_t modifiers, + uint32_t scan_code, + bool is_down); private: PlatformView* FindViewById(int view_id); diff --git a/shell/platform/tizen/channels/text_input_channel.cc b/shell/platform/tizen/channels/text_input_channel.cc index 0c75b04f18ef5..66497914d79a8 100644 --- a/shell/platform/tizen/channels/text_input_channel.cc +++ b/shell/platform/tizen/channels/text_input_channel.cc @@ -4,8 +4,6 @@ #include "text_input_channel.h" -#include - #include "flutter/shell/platform/common/json_method_codec.h" #include "flutter/shell/platform/tizen/flutter_tizen_engine.h" #include "flutter/shell/platform/tizen/logger.h" @@ -50,82 +48,78 @@ bool IsAsciiPrintableKey(char ch) { TextInputChannel::TextInputChannel( BinaryMessenger* messenger, - std::unique_ptr input_method_context) + TizenInputMethodContext* input_method_context) : channel_(std::make_unique>( messenger, kChannelName, &JsonMethodCodec::GetInstance())), - input_method_context_(std::move(input_method_context)) { + input_method_context_(input_method_context) { channel_->SetMethodCallHandler( [this](const MethodCall& call, std::unique_ptr> result) { HandleMethodCall(call, std::move(result)); }); +} - // Set input method callbacks. - input_method_context_->SetOnPreeditStart([this]() { - FT_LOG(Debug) << "onPreeditStart"; - active_model_->BeginComposing(); - }); - - input_method_context_->SetOnPreeditChanged( - [this](std::string str, int cursor_pos) -> void { - FT_LOG(Debug) << "onPreedit: str[" << str << "] cursor_pos[" - << cursor_pos << "]"; - if (str == "") { - // Enter pre-edit end stage. - return; - } - active_model_->UpdateComposingText(str); - SendStateUpdate(*active_model_); - }); +TextInputChannel::~TextInputChannel() {} - input_method_context_->SetOnPreeditEnd([this]() { - FT_LOG(Debug) << "onPreeditEnd"; +void TextInputChannel::OnComposeBegin() { + if (active_model_ == nullptr) { + return; + } + active_model_->BeginComposing(); +} + +void TextInputChannel::OnComposeChange(const std::string& str, int cursor_pos) { + if (active_model_ == nullptr) { + return; + } + if (str == "") { + // Enter pre-edit end stage. + return; + } + active_model_->UpdateComposingText(str); + SendStateUpdate(); +} - // Delete preedit-string, it will be committed. - int count = active_model_->composing_range().extent() - - active_model_->composing_range().base(); +void TextInputChannel::OnComposeEnd() { + if (active_model_ == nullptr) { + return; + } + // Delete preedit-string, it will be committed. + int count = active_model_->composing_range().extent() - + active_model_->composing_range().base(); + + active_model_->CommitComposing(); + active_model_->EndComposing(); + active_model_->DeleteSurrounding(-count, count); + SendStateUpdate(); +} +void TextInputChannel::OnCommit(const std::string& str) { + if (active_model_ == nullptr) { + return; + } + active_model_->AddText(str); + if (active_model_->composing()) { active_model_->CommitComposing(); active_model_->EndComposing(); - - active_model_->DeleteSurrounding(-count, count); - - SendStateUpdate(*active_model_); - }); - - input_method_context_->SetOnCommit([this](std::string str) -> void { - FT_LOG(Debug) << "OnCommit: str[" << str << "]"; - active_model_->AddText(str); - if (active_model_->composing()) { - active_model_->CommitComposing(); - active_model_->EndComposing(); - } - SendStateUpdate(*active_model_); - }); - - input_method_context_->SetOnInputPanelStateChanged([this](int state) { - if (state == ECORE_IMF_INPUT_PANEL_STATE_HIDE) { - // Fallback for HW back-key. - input_method_context_->HideInputPanel(); - Reset(); - is_software_keyboard_showing_ = false; - } else { - is_software_keyboard_showing_ = true; - } - }); + } + SendStateUpdate(); } -TextInputChannel::~TextInputChannel() {} - -bool TextInputChannel::SendKeyEvent(Ecore_Event_Key* key, bool is_down) { - if (!active_model_) { +bool TextInputChannel::SendKey(const char* key, + const char* string, + const char* compose, + uint32_t modifiers, + uint32_t scan_code, + bool is_down) { + if (active_model_ == nullptr) { return false; } - if (!FilterEvent(key, is_down) && is_down) { - HandleUnfilteredEvent(key); + if (is_down) { + HandleKey(key, string, modifiers); } return true; @@ -135,13 +129,12 @@ void TextInputChannel::HandleMethodCall( const MethodCall& method_call, std::unique_ptr> result) { const std::string& method = method_call.method_name(); - FT_LOG(Debug) << "method: " << method; if (method.compare(kShowMethod) == 0) { input_method_context_->ShowInputPanel(); } else if (method.compare(kHideMethod) == 0) { input_method_context_->HideInputPanel(); - Reset(); + input_method_context_->ResetInputMethodContext(); } else if (method.compare(kSetPlatformViewClient) == 0) { result->NotImplemented(); return; @@ -210,7 +203,7 @@ void TextInputChannel::HandleMethodCall( active_model_ = std::make_unique(); } else if (method.compare(kSetEditingStateMethod) == 0) { - Reset(); + input_method_context_->ResetInputMethodContext(); if (!method_call.arguments() || method_call.arguments()->IsNull()) { result->Error(kBadArgumentError, "Method invoked without args."); return; @@ -269,7 +262,7 @@ void TextInputChannel::HandleMethodCall( static_cast(composing_extent_value)), cursor_offset); } - SendStateUpdate(*active_model_); + SendStateUpdate(); } else { result->NotImplemented(); return; @@ -279,12 +272,12 @@ void TextInputChannel::HandleMethodCall( result->Success(); } -void TextInputChannel::SendStateUpdate(const TextInputModel& model) { +void TextInputChannel::SendStateUpdate() { auto args = std::make_unique(rapidjson::kArrayType); rapidjson::MemoryPoolAllocator<>& allocator = args->GetAllocator(); args->PushBack(client_id_, allocator); - TextRange selection = model.selection(); + TextRange selection = active_model_->selection(); rapidjson::Value editing_state(rapidjson::kObjectType); int composing_base = active_model_->composing() ? active_model_->composing_range().base() : -1; @@ -300,56 +293,21 @@ void TextInputChannel::SendStateUpdate(const TextInputModel& model) { editing_state.AddMember(kSelectionExtentKey, selection.extent(), allocator); editing_state.AddMember(kSelectionIsDirectionalKey, false, allocator); editing_state.AddMember( - kTextKey, rapidjson::Value(model.GetText(), allocator).Move(), allocator); + kTextKey, rapidjson::Value(active_model_->GetText(), allocator).Move(), + allocator); args->PushBack(editing_state, allocator); - FT_LOG(Debug) << "Send text:[" << model.GetText() << "]"; channel_->InvokeMethod(kUpdateEditingStateMethod, std::move(args)); } -bool TextInputChannel::FilterEvent(Ecore_Event_Key* event, bool is_down) { - bool handled = false; - -#ifdef WEARABLE_PROFILE - // Hardware keyboard is not supported on watch devices. - bool is_ime = true; - // FIXME: Only for wearable. - if (is_ime && strcmp(event->key, "Select") == 0) { - is_in_select_mode_ = true; - FT_LOG(Debug) << "Entering select mode."; - } -#else - const char* device_name = ecore_device_name_get(event->dev); - bool is_ime = device_name ? strcmp(device_name, "ime") == 0 : true; -#endif - - if (ShouldNotFilterEvent(event->key, is_ime)) { - FT_LOG(Info) << "Force redirect an IME key event: " << event->keyname; - Reset(); - return false; - } - - handled = - input_method_context_->FilterEvent(event, is_ime ? "ime" : "", is_down); - -#ifdef WEARABLE_PROFILE - if (!handled && !strcmp(event->key, "Return") && is_in_select_mode_) { - is_in_select_mode_ = false; - handled = true; - FT_LOG(Debug) << "Leaving select mode."; - } -#endif - - return handled; -} - -void TextInputChannel::HandleUnfilteredEvent(Ecore_Event_Key* event) { - bool select = !strcmp(event->key, "Select"); - bool shift = event->modifiers & ECORE_SHIFT; +void TextInputChannel::HandleKey(const char* key, + const char* string, + uint32_t modifires) { + bool shift = modifires & ECORE_SHIFT; bool needs_update = false; - std::string key = event->key; + std::string key_str = key; - if (key == "Left") { + if (key_str == "Left") { if (shift) { TextRange selection = active_model_->selection(); needs_update = active_model_->SetSelection( @@ -357,7 +315,7 @@ void TextInputChannel::HandleUnfilteredEvent(Ecore_Event_Key* event) { } else { needs_update = active_model_->MoveCursorBack(); } - } else if (key == "Right") { + } else if (key_str == "Right") { if (shift) { TextRange selection = active_model_->selection(); needs_update = active_model_->SetSelection( @@ -365,42 +323,46 @@ void TextInputChannel::HandleUnfilteredEvent(Ecore_Event_Key* event) { } else { needs_update = active_model_->MoveCursorForward(); } - } else if (key == "End") { + } else if (key_str == "End") { if (shift) { needs_update = active_model_->SelectToEnd(); } else { needs_update = active_model_->MoveCursorToEnd(); } - } else if (key == "Home") { + } else if (key_str == "Home") { if (shift) { needs_update = active_model_->SelectToBeginning(); } else { needs_update = active_model_->MoveCursorToBeginning(); } - } else if (key == "BackSpace") { + } else if (key_str == "BackSpace") { needs_update = active_model_->Backspace(); - } else if (key == "Delete") { + } else if (key_str == "Delete") { needs_update = active_model_->Delete(); - } else if (event->string && strlen(event->string) == 1 && - IsAsciiPrintableKey(event->string[0])) { - active_model_->AddCodePoint(event->string[0]); + } else if (string && strlen(string) == 1 && IsAsciiPrintableKey(string[0])) { + active_model_->AddCodePoint(string[0]); needs_update = true; - } else if (key == "Return" || (select && !is_in_select_mode_)) { - EnterPressed(active_model_.get(), select); + } else if (key_str == "Return") { + EnterPressed(); + return; +#ifdef TV_PROFILE + } else if (key_str == "Select") { + SelectPressed(); return; } else { +#endif FT_LOG(Warn) << "Key[" << key << "] is unhandled."; } if (needs_update) { - SendStateUpdate(*active_model_); + SendStateUpdate(); } } -void TextInputChannel::EnterPressed(TextInputModel* model, bool select) { - if (!select && input_type_ == kMultilineInputType) { - model->AddCodePoint('\n'); - SendStateUpdate(*model); +void TextInputChannel::EnterPressed() { + if (input_type_ == kMultilineInputType) { + active_model_->AddCodePoint('\n'); + SendStateUpdate(); } auto args = std::make_unique(rapidjson::kArrayType); rapidjson::MemoryPoolAllocator<>& allocator = args->GetAllocator(); @@ -410,24 +372,15 @@ void TextInputChannel::EnterPressed(TextInputModel* model, bool select) { channel_->InvokeMethod(kPerformActionMethod, std::move(args)); } -void TextInputChannel::Reset() { - is_in_select_mode_ = false; - input_method_context_->ResetInputMethodContext(); -} +#ifdef TV_PROFILE +void TextInputChannel::SelectPressed() { + auto args = std::make_unique(rapidjson::kArrayType); + rapidjson::MemoryPoolAllocator<>& allocator = args->GetAllocator(); + args->PushBack(client_id_, allocator); + args->PushBack(rapidjson::Value(input_action_, allocator).Move(), allocator); -bool TextInputChannel::ShouldNotFilterEvent(std::string key, bool is_ime) { - // Force redirect to HandleUnfilteredEvent(especially on TV) - // If you don't do this, it will affects the input panel. - // For example, when the left key of the input panel is pressed, the focus - // of the input panel is shifted to left! - // What we want is to move only the cursor on the text editor. - if (is_ime && !is_in_select_mode_ && - (key == "Left" || key == "Right" || key == "Up" || key == "Down" || - key == "End" || key == "Home" || key == "BackSpace" || key == "Delete" || - key == "Select")) { - return true; - } - return false; + channel_->InvokeMethod(kPerformActionMethod, std::move(args)); } +#endif } // namespace flutter diff --git a/shell/platform/tizen/channels/text_input_channel.h b/shell/platform/tizen/channels/text_input_channel.h index 092ad3b08e5f5..4f9eea2034349 100644 --- a/shell/platform/tizen/channels/text_input_channel.h +++ b/shell/platform/tizen/channels/text_input_channel.h @@ -5,10 +5,6 @@ #ifndef EMBEDDER_TEXT_INPUT_CHANNEL_H_ #define EMBEDDER_TEXT_INPUT_CHANNEL_H_ -#define EFL_BETA_API_SUPPORT -#include -#include - #include #include @@ -22,35 +18,63 @@ namespace flutter { class TextInputChannel { public: - explicit TextInputChannel( - BinaryMessenger* messenger, - std::unique_ptr input_method_context); + explicit TextInputChannel(BinaryMessenger* messenger, + TizenInputMethodContext* input_method_context); virtual ~TextInputChannel(); - bool IsSoftwareKeyboardShowing() { return is_software_keyboard_showing_; } + void OnComposeBegin(); + + void OnComposeChange(const std::string& str, int cursor_pos); + + void OnComposeEnd(); - bool SendKeyEvent(Ecore_Event_Key* key, bool is_down); + void OnCommit(const std::string& str); + + bool SendKey(const char* key, + const char* string, + const char* compose, + uint32_t modifiers, + uint32_t scan_code, + bool is_down); private: + // Called when a method is called on |channel_|; void HandleMethodCall( const MethodCall& method_call, std::unique_ptr> result); - void SendStateUpdate(const TextInputModel& model); - bool FilterEvent(Ecore_Event_Key* event, bool is_down); - void HandleUnfilteredEvent(Ecore_Event_Key* event); - void EnterPressed(TextInputModel* model, bool select); - void Reset(); - bool ShouldNotFilterEvent(std::string key, bool is_ime); + // Sends the current state of |active_model_| to the Flutter engine. + void SendStateUpdate(); + + void HandleKey(const char* key, const char* string, uint32_t modifiers); + + // Sends an action triggered by the Enter key to the Flutter engine. + void EnterPressed(); + +#ifdef TV_PROFILE + // Sends an action triggered by the Select key to the Flutter engine. + void SelectPressed(); +#endif + + // The MethodChannel used for communication with the Flutter engine. std::unique_ptr> channel_; + + // The active model. nullptr if not set. std::unique_ptr active_model_; - std::unique_ptr input_method_context_; + // The Tizen input method context. nullptr if not set. + TizenInputMethodContext* input_method_context_ = nullptr; + + // The active client id. int client_id_ = 0; - bool is_software_keyboard_showing_ = false; + + // An action requested by the user on the input client. See available options: + // https://api.flutter.dev/flutter/services/TextInputAction-class.html std::string input_action_; + + // Keyboard type of the client. See available options: + // https://api.flutter.dev/flutter/services/TextInputType-class.html std::string input_type_; - bool is_in_select_mode_ = false; }; } // namespace flutter diff --git a/shell/platform/tizen/external_texture.h b/shell/platform/tizen/external_texture.h index 4d3f6e913d030..53c77acaa8074 100644 --- a/shell/platform/tizen/external_texture.h +++ b/shell/platform/tizen/external_texture.h @@ -12,7 +12,6 @@ #include "flutter/shell/platform/embedder/embedder.h" #ifdef TIZEN_RENDERER_EVAS_GL -#undef EFL_BETA_API_SUPPORT #include #else #include diff --git a/shell/platform/tizen/external_texture_pixel_gl.cc b/shell/platform/tizen/external_texture_pixel_gl.cc index 85573ea396204..340ccc8773fb7 100644 --- a/shell/platform/tizen/external_texture_pixel_gl.cc +++ b/shell/platform/tizen/external_texture_pixel_gl.cc @@ -5,7 +5,6 @@ #include "external_texture_pixel_gl.h" #ifdef TIZEN_RENDERER_EVAS_GL -#undef EFL_BETA_API_SUPPORT #include "tizen_evas_gl_helper.h" extern Evas_GL* g_evas_gl; EVAS_GL_GLOBAL_GLES2_DECLARE(); diff --git a/shell/platform/tizen/external_texture_surface_gl.cc b/shell/platform/tizen/external_texture_surface_gl.cc index dcbc0d9001704..99b6552269eba 100644 --- a/shell/platform/tizen/external_texture_surface_gl.cc +++ b/shell/platform/tizen/external_texture_surface_gl.cc @@ -7,7 +7,6 @@ #include #ifdef TIZEN_RENDERER_EVAS_GL -#undef EFL_BETA_API_SUPPORT #include "tizen_evas_gl_helper.h" extern Evas_GL* g_evas_gl; EVAS_GL_GLOBAL_GLES2_DECLARE(); diff --git a/shell/platform/tizen/flutter_tizen_view.cc b/shell/platform/tizen/flutter_tizen_view.cc index f1c029aa58cae..32e04361084de 100644 --- a/shell/platform/tizen/flutter_tizen_view.cc +++ b/shell/platform/tizen/flutter_tizen_view.cc @@ -61,8 +61,7 @@ void FlutterTizenView::SetEngine(std::unique_ptr engine) { std::make_unique(messenger, window_.get()); window_channel_ = std::make_unique(messenger, window_.get()); text_input_channel_ = std::make_unique( - internal_plugin_registrar_->messenger(), - std::make_unique(window_.get())); + internal_plugin_registrar_->messenger(), window_->input_method_context()); } void FlutterTizenView::CreateRenderSurface() { @@ -194,27 +193,33 @@ void FlutterTizenView::OnScroll(double x, delta_y * scroll_offset_multiplier, timestamp, device_kind, device_id); } -void FlutterTizenView::OnKey(Ecore_Event_Key* event, bool is_down) { +void FlutterTizenView::OnKey(const char* key, + const char* string, + const char* compose, + uint32_t modifiers, + uint32_t scan_code, + bool is_down) { if (is_down) { - FT_LOG(Info) << "Key symbol: " << event->key << ", code: 0x" << std::setw(8) - << std::setfill('0') << std::right << std::hex - << event->keycode; + FT_LOG(Info) << "Key symbol: " << key << ", code: 0x" << std::setw(8) + << std::setfill('0') << std::right << std::hex << scan_code; } if (text_input_channel_) { - if (text_input_channel_->SendKeyEvent(event, is_down)) { + if (text_input_channel_->SendKey(key, string, compose, modifiers, scan_code, + is_down)) { return; } } if (engine_->platform_view_channel()) { - engine_->platform_view_channel()->SendKeyEvent(event, is_down); + engine_->platform_view_channel()->SendKey(key, string, compose, modifiers, + scan_code, is_down); } if (engine_->key_event_channel()) { - engine_->key_event_channel()->SendKeyEvent( - event, is_down, - [engine = engine_.get(), symbol = std::string(event->key), + engine_->key_event_channel()->SendKey( + key, string, compose, modifiers, scan_code, is_down, + [engine = engine_.get(), symbol = std::string(key), is_down](bool handled) { if (handled) { return; @@ -230,6 +235,22 @@ void FlutterTizenView::OnKey(Ecore_Event_Key* event, bool is_down) { } } +void FlutterTizenView::OnComposeBegin() { + text_input_channel_->OnComposeBegin(); +} + +void FlutterTizenView::OnComposeChange(const std::string& str, int cursor_pos) { + text_input_channel_->OnComposeChange(str, cursor_pos); +} + +void FlutterTizenView::OnComposeEnd() { + text_input_channel_->OnComposeEnd(); +} + +void FlutterTizenView::OnCommit(const std::string& str) { + text_input_channel_->OnCommit(str); +} + void FlutterTizenView::SendInitialGeometry() { OnRotate(window_->GetRotation()); } diff --git a/shell/platform/tizen/flutter_tizen_view.h b/shell/platform/tizen/flutter_tizen_view.h index b59fa6d7d0606..f31b597c85d3f 100644 --- a/shell/platform/tizen/flutter_tizen_view.h +++ b/shell/platform/tizen/flutter_tizen_view.h @@ -8,8 +8,6 @@ #include -#include - #include "flutter/shell/platform/common/client_wrapper/include/flutter/plugin_registrar.h" #include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/tizen/channels/platform_channel.h" @@ -83,7 +81,20 @@ class FlutterTizenView { FlutterPointerDeviceKind device_kind, int32_t device_id); - void OnKey(Ecore_Event_Key* event, bool is_down); + void OnKey(const char* key, + const char* string, + const char* compose, + uint32_t modifiers, + uint32_t scan_code, + bool is_down); + + void OnComposeBegin(); + + void OnComposeChange(const std::string& str, int cursor_pos); + + void OnComposeEnd(); + + void OnCommit(const std::string& str); FlutterTransformation GetFlutterTransformation() { return flutter_transformation_; @@ -91,6 +102,8 @@ class FlutterTizenView { void SendInitialGeometry(); + TextInputChannel* text_input_channel() { return text_input_channel_.get(); } + private: // Sends a window metrics update to the Flutter engine using current window // dimensions in physical. diff --git a/shell/platform/tizen/public/flutter_platform_view.h b/shell/platform/tizen/public/flutter_platform_view.h index c0b18949976f5..3da913557fb68 100644 --- a/shell/platform/tizen/public/flutter_platform_view.h +++ b/shell/platform/tizen/public/flutter_platform_view.h @@ -5,7 +5,6 @@ #ifndef FLUTTER_SHELL_PLATFORM_TIZEN_PUBLIC_FLUTTER_PLATFORM_VIEW_H_ #define FLUTTER_SHELL_PLATFORM_TIZEN_PUBLIC_FLUTTER_PLATFORM_VIEW_H_ -#include #include #include #include @@ -46,8 +45,12 @@ class PlatformView { bool IsFocused() { return is_focused_; } - virtual void DispatchKeyDownEvent(Ecore_Event_Key* event) = 0; - virtual void DispatchKeyUpEvent(Ecore_Event_Key* event) = 0; + virtual void SendKey(const char* key, + const char* string, + const char* compose, + uint32_t modifiers, + uint32_t scan_code, + bool is_down) = 0; private: flutter::PluginRegistrar* registrar_; diff --git a/shell/platform/tizen/tizen_input_method_context.cc b/shell/platform/tizen/tizen_input_method_context.cc index 4b83d1b53dbf6..72d7282d74486 100644 --- a/shell/platform/tizen/tizen_input_method_context.cc +++ b/shell/platform/tizen/tizen_input_method_context.cc @@ -5,7 +5,6 @@ #include "tizen_input_method_context.h" #include "flutter/shell/platform/tizen/logger.h" -#include "flutter/shell/platform/tizen/tizen_window.h" namespace { @@ -103,9 +102,7 @@ T EcoreEventKeyToEcoreImfEvent(Ecore_Event_Key* event, const char* dev_name) { namespace flutter { -TizenInputMethodContext::TizenInputMethodContext(TizenWindow* window) - : window_(window) { - FT_ASSERT(window_); +TizenInputMethodContext::TizenInputMethodContext(uintptr_t window_id) { ecore_imf_init(); const char* imf_id = ecore_imf_context_default_id_get(); @@ -124,8 +121,8 @@ TizenInputMethodContext::TizenInputMethodContext(TizenWindow* window) return; } - ecore_imf_context_client_window_set( - imf_context_, reinterpret_cast(window_->GetWindowId())); + ecore_imf_context_client_window_set(imf_context_, + reinterpret_cast(window_id)); SetContextOptions(); SetInputPanelOptions(); RegisterEventCallbacks(); @@ -141,28 +138,67 @@ TizenInputMethodContext::~TizenInputMethodContext() { ecore_imf_shutdown(); } -bool TizenInputMethodContext::FilterEvent(Ecore_Event_Key* event, - const char* dev_name, - bool is_down) { +bool TizenInputMethodContext::HandleEcoreEventKey(Ecore_Event_Key* event, + bool is_down) { FT_ASSERT(imf_context_); FT_ASSERT(event); - FT_ASSERT(dev_name); +#ifdef WEARABLE_PROFILE + // Hardware keyboard is not supported on watch devices. + const char* device_name = "ime"; + bool is_ime = true; +#else + const char* device_name = ecore_device_name_get(event->dev); + bool is_ime = device_name ? strcmp(device_name, "ime") == 0 : true; +#endif + + if (ShouldIgnoreKey(event->key, is_ime)) { + return false; + } if (is_down) { Ecore_IMF_Event_Key_Down imf_event = - EcoreEventKeyToEcoreImfEvent(event, dev_name); + EcoreEventKeyToEcoreImfEvent(event, + device_name); return ecore_imf_context_filter_event( imf_context_, ECORE_IMF_EVENT_KEY_DOWN, reinterpret_cast(&imf_event)); } else { Ecore_IMF_Event_Key_Up imf_event = - EcoreEventKeyToEcoreImfEvent(event, dev_name); + EcoreEventKeyToEcoreImfEvent(event, + device_name); return ecore_imf_context_filter_event( imf_context_, ECORE_IMF_EVENT_KEY_UP, reinterpret_cast(&imf_event)); } } +bool TizenInputMethodContext::HandleEvasEventKeyDown( + Evas_Event_Key_Down* event) { + if (ShouldIgnoreKey(event->key, true)) { + return false; + } + + Ecore_IMF_Event_Key_Down imf_event; + ecore_imf_evas_event_key_down_wrap(event, &imf_event); + + return ecore_imf_context_filter_event( + imf_context_, ECORE_IMF_EVENT_KEY_DOWN, + reinterpret_cast(&imf_event)); +} + +bool TizenInputMethodContext::HandleEvasEventKeyUp(Evas_Event_Key_Up* event) { + if (ShouldIgnoreKey(event->key, true)) { + return false; + } + + Ecore_IMF_Event_Key_Up imf_event; + ecore_imf_evas_event_key_up_wrap(event, &imf_event); + + return ecore_imf_context_filter_event( + imf_context_, ECORE_IMF_EVENT_KEY_UP, + reinterpret_cast(&imf_event)); +} + InputPanelGeometry TizenInputMethodContext::GetInputPanelGeometry() { FT_ASSERT(imf_context_); InputPanelGeometry geometry; @@ -188,6 +224,12 @@ void TizenInputMethodContext::HideInputPanel() { ecore_imf_context_input_panel_hide(imf_context_); } +bool TizenInputMethodContext::IsInputPanelShown() { + Ecore_IMF_Input_Panel_State state = + ecore_imf_context_input_panel_state_get(imf_context_); + return state == ECORE_IMF_INPUT_PANEL_STATE_SHOW; +} + void TizenInputMethodContext::SetInputPanelLayout( const std::string& input_type) { FT_ASSERT(imf_context_); @@ -269,17 +311,6 @@ void TizenInputMethodContext::RegisterEventCallbacks() { ecore_imf_context_event_callback_add( imf_context_, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, event_callbacks_[ECORE_IMF_CALLBACK_PREEDIT_CHANGED], this); - - // input panel state callback - ecore_imf_context_input_panel_event_callback_add( - imf_context_, ECORE_IMF_INPUT_PANEL_STATE_EVENT, - [](void* data, Ecore_IMF_Context* context, int value) { - auto* self = static_cast(data); - if (self->on_input_panel_state_changed_) { - self->on_input_panel_state_changed_(value); - } - }, - this); } void TizenInputMethodContext::UnregisterEventCallbacks() { @@ -296,7 +327,6 @@ void TizenInputMethodContext::UnregisterEventCallbacks() { ecore_imf_context_event_callback_del( imf_context_, ECORE_IMF_CALLBACK_PREEDIT_END, event_callbacks_[ECORE_IMF_CALLBACK_PREEDIT_END]); - ecore_imf_context_input_panel_event_callback_clear(imf_context_); } void TizenInputMethodContext::SetContextOptions() { @@ -316,4 +346,20 @@ void TizenInputMethodContext::SetInputPanelOptions() { imf_context_, ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC); } +bool TizenInputMethodContext::ShouldIgnoreKey(std::string key, bool is_ime) { + // The keys below should be handled in the text_input_channel. + if (is_ime && (key == "Left" || key == "Right" || key == "Up" || + key == "Down" || key == "End" || key == "Home" || + key == "BackSpace" || key == "Delete")) { + return true; + } +#ifdef TV_PROFILE + if (is_ime && key == "Select") { + return true; + } +#endif + + return false; +} + } // namespace flutter diff --git a/shell/platform/tizen/tizen_input_method_context.h b/shell/platform/tizen/tizen_input_method_context.h index dcc069c36791e..55dd4a960c310 100644 --- a/shell/platform/tizen/tizen_input_method_context.h +++ b/shell/platform/tizen/tizen_input_method_context.h @@ -5,8 +5,8 @@ #ifndef EMBEDDER_TIZEN_INPUT_METHOD_CONTEXT_H_ #define EMBEDDER_TIZEN_INPUT_METHOD_CONTEXT_H_ -#define EFL_BETA_API_SUPPORT #include +#include #include #include @@ -19,9 +19,6 @@ using OnCommit = std::function; using OnPreeditChanged = std::function; using OnPreeditStart = std::function; using OnPreeditEnd = std::function; -using OnInputPanelStateChanged = std::function; - -class TizenWindow; struct InputPanelGeometry { int32_t x = 0, y = 0, w = 0, h = 0; @@ -29,10 +26,14 @@ struct InputPanelGeometry { class TizenInputMethodContext { public: - TizenInputMethodContext(TizenWindow* window); + TizenInputMethodContext(uintptr_t window_id); ~TizenInputMethodContext(); - bool FilterEvent(Ecore_Event_Key* event, const char* dev_name, bool is_down); + bool HandleEcoreEventKey(Ecore_Event_Key* event, bool is_down); + + bool HandleEvasEventKeyDown(Evas_Event_Key_Down* event); + + bool HandleEvasEventKeyUp(Evas_Event_Key_Up* event); InputPanelGeometry GetInputPanelGeometry(); @@ -42,6 +43,8 @@ class TizenInputMethodContext { void HideInputPanel(); + bool IsInputPanelShown(); + void SetInputPanelLayout(const std::string& layout); void SetInputPanelLayoutVariation(bool is_signed, bool is_decimal); @@ -58,10 +61,6 @@ class TizenInputMethodContext { void SetOnPreeditEnd(OnPreeditEnd callback) { on_preedit_end_ = callback; } - void SetOnInputPanelStateChanged(OnInputPanelStateChanged callback) { - on_input_panel_state_changed_ = callback; - } - private: void RegisterEventCallbacks(); void UnregisterEventCallbacks(); @@ -69,13 +68,13 @@ class TizenInputMethodContext { void SetContextOptions(); void SetInputPanelOptions(); - TizenWindow* window_ = nullptr; + bool ShouldIgnoreKey(std::string key, bool is_ime); + Ecore_IMF_Context* imf_context_ = nullptr; OnCommit on_commit_; OnPreeditChanged on_preedit_changed_; OnPreeditStart on_preedit_start_; OnPreeditEnd on_preedit_end_; - OnInputPanelStateChanged on_input_panel_state_changed_; std::unordered_map event_callbacks_; }; diff --git a/shell/platform/tizen/tizen_renderer_egl.cc b/shell/platform/tizen/tizen_renderer_egl.cc index 0b88fc2212235..327797e0d23fd 100644 --- a/shell/platform/tizen/tizen_renderer_egl.cc +++ b/shell/platform/tizen/tizen_renderer_egl.cc @@ -4,6 +4,7 @@ #include "tizen_renderer_egl.h" +#define EFL_BETA_API_SUPPORT #include #include #include diff --git a/shell/platform/tizen/tizen_renderer_egl.h b/shell/platform/tizen/tizen_renderer_egl.h index 74708e3b65fc6..a981ae1a76cd4 100644 --- a/shell/platform/tizen/tizen_renderer_egl.h +++ b/shell/platform/tizen/tizen_renderer_egl.h @@ -5,7 +5,6 @@ #ifndef EMBEDDER_TIZEN_RENDERER_EGL_H_ #define EMBEDDER_TIZEN_RENDERER_EGL_H_ -#define EFL_BETA_API_SUPPORT #include #include diff --git a/shell/platform/tizen/tizen_renderer_evas_gl.h b/shell/platform/tizen/tizen_renderer_evas_gl.h index badba04499004..fd41d8a5c8097 100644 --- a/shell/platform/tizen/tizen_renderer_evas_gl.h +++ b/shell/platform/tizen/tizen_renderer_evas_gl.h @@ -7,7 +7,6 @@ #include -#undef EFL_BETA_API_SUPPORT #include #include diff --git a/shell/platform/tizen/tizen_window.h b/shell/platform/tizen/tizen_window.h index b4a6ed94d5d2b..a058e2684b71c 100644 --- a/shell/platform/tizen/tizen_window.h +++ b/shell/platform/tizen/tizen_window.h @@ -10,6 +10,8 @@ #include #include +#include "flutter/shell/platform/tizen/tizen_input_method_context.h" + namespace flutter { class FlutterTizenView; @@ -20,8 +22,6 @@ class TizenWindow { int32_t left = 0, top = 0, width = 0, height = 0; }; - TizenWindow(); - virtual ~TizenWindow() = default; // Sets the delegate used to communicate state changes from window to view @@ -65,6 +65,10 @@ class TizenWindow { // This is a temporary implementation that is only used by the window channel. virtual void OnGeometryChanged(Geometry geometry) = 0; + TizenInputMethodContext* input_method_context() { + return input_method_context_.get(); + } + protected: explicit TizenWindow(Geometry geometry, bool transparent, @@ -81,6 +85,9 @@ class TizenWindow { bool top_level_ = false; FlutterTizenView* view_ = nullptr; + + // The Tizen input method context. nullptr if not set. + std::unique_ptr input_method_context_; }; } // namespace flutter diff --git a/shell/platform/tizen/tizen_window_ecore_wl2.cc b/shell/platform/tizen/tizen_window_ecore_wl2.cc index 4353f4d30c256..31ecc8a8fdc0a 100644 --- a/shell/platform/tizen/tizen_window_ecore_wl2.cc +++ b/shell/platform/tizen/tizen_window_ecore_wl2.cc @@ -30,6 +30,7 @@ TizenWindowEcoreWl2::TizenWindowEcoreWl2(Geometry geometry, SetWindowOptions(); RegisterEventHandlers(); + PrepareInputMethod(); Show(); } @@ -243,7 +244,16 @@ void TizenWindowEcoreWl2::RegisterEventHandlers() { if (self->view_) { auto* key_event = reinterpret_cast(event); if (key_event->window == self->GetWindowId()) { - self->view_->OnKey(key_event, true); + int handled = false; + if (self->input_method_context_->IsInputPanelShown()) { + handled = self->input_method_context_->HandleEcoreEventKey( + key_event, true); + } + if (!handled) { + self->view_->OnKey(key_event->key, key_event->string, + key_event->compose, key_event->modifiers, + key_event->keycode, true); + } return ECORE_CALLBACK_DONE; } } @@ -258,7 +268,16 @@ void TizenWindowEcoreWl2::RegisterEventHandlers() { if (self->view_) { auto* key_event = reinterpret_cast(event); if (key_event->window == self->GetWindowId()) { - self->view_->OnKey(key_event, false); + int handled = false; + if (self->input_method_context_->IsInputPanelShown()) { + handled = self->input_method_context_->HandleEcoreEventKey( + key_event, false); + } + if (!handled) { + self->view_->OnKey(key_event->key, key_event->string, + key_event->compose, key_event->modifiers, + key_event->keycode, false); + } return ECORE_CALLBACK_DONE; } } @@ -393,4 +412,20 @@ void TizenWindowEcoreWl2::SetTizenPolicyNotificationLevel(int level) { tizen_policy_, ecore_wl2_window_surface_get(ecore_wl2_window_), level); } +void TizenWindowEcoreWl2::PrepareInputMethod() { + input_method_context_ = + std::make_unique(GetWindowId()); + + // Set input method callbacks. + input_method_context_->SetOnPreeditStart( + [this]() { view_->OnComposeBegin(); }); + input_method_context_->SetOnPreeditChanged( + [this](std::string str, int cursor_pos) { + view_->OnComposeChange(str, cursor_pos); + }); + input_method_context_->SetOnPreeditEnd([this]() { view_->OnComposeEnd(); }); + input_method_context_->SetOnCommit( + [this](std::string str) { view_->OnCommit(str); }); +} + } // namespace flutter diff --git a/shell/platform/tizen/tizen_window_ecore_wl2.h b/shell/platform/tizen/tizen_window_ecore_wl2.h index 25dc1f56f9287..026c949e63cfc 100644 --- a/shell/platform/tizen/tizen_window_ecore_wl2.h +++ b/shell/platform/tizen/tizen_window_ecore_wl2.h @@ -65,6 +65,8 @@ class TizenWindowEcoreWl2 : public TizenWindow { void SetTizenPolicyNotificationLevel(int level); + void PrepareInputMethod(); + Ecore_Wl2_Display* ecore_wl2_display_ = nullptr; Ecore_Wl2_Window* ecore_wl2_window_ = nullptr; diff --git a/shell/platform/tizen/tizen_window_elementary.cc b/shell/platform/tizen/tizen_window_elementary.cc index 49725fe0d6fc9..c3e3341befb66 100644 --- a/shell/platform/tizen/tizen_window_elementary.cc +++ b/shell/platform/tizen/tizen_window_elementary.cc @@ -17,6 +17,20 @@ static const int kScrollDirectionVertical = 0; static const int kScrollDirectionHorizontal = 1; static const int kScrollOffsetMultiplier = 20; +uint32_t EvasModifierToEcoreEventModifiers(const Evas_Modifier* evas_modifier) { + uint32_t modifiers = 0; + if (evas_key_modifier_is_set(evas_modifier, "Control")) { + modifiers |= ECORE_EVENT_MODIFIER_CTRL; + } + if (evas_key_modifier_is_set(evas_modifier, "Alt")) { + modifiers |= ECORE_EVENT_MODIFIER_ALT; + } + if (evas_key_modifier_is_set(evas_modifier, "Shift")) { + modifiers |= ECORE_EVENT_MODIFIER_SHIFT; + } + return modifiers; +} + } // namespace namespace flutter { @@ -33,6 +47,7 @@ TizenWindowElementary::TizenWindowElementary(Geometry geometry, SetWindowOptions(); RegisterEventHandlers(); + PrepareInputMethod(); Show(); } @@ -121,7 +136,7 @@ void TizenWindowElementary::SetWindowOptions() { } void TizenWindowElementary::RegisterEventHandlers() { - rotatoin_changed_callback_ = [](void* data, Evas_Object* object, + rotation_changed_callback_ = [](void* data, Evas_Object* object, void* event_info) { auto* self = reinterpret_cast(data); if (self->view_) { @@ -134,7 +149,7 @@ void TizenWindowElementary::RegisterEventHandlers() { } }; evas_object_smart_callback_add(elm_win_, "rotation,changed", - rotatoin_changed_callback_, this); + rotation_changed_callback_, this); evas_object_callbacks_[EVAS_CALLBACK_MOUSE_DOWN] = [](void* data, Evas* evas, Evas_Object* object, void* event_info) { @@ -217,41 +232,59 @@ void TizenWindowElementary::RegisterEventHandlers() { elm_win_, EVAS_CALLBACK_MOUSE_WHEEL, evas_object_callbacks_[EVAS_CALLBACK_MOUSE_WHEEL], this); - // FIXME: ues EVAS_CALLBACK_KEY_DOWN, EVAS_CALLBACK_KEY_UP - ecore_event_key_handlers_.push_back(ecore_event_handler_add( - ECORE_EVENT_KEY_DOWN, - [](void* data, int type, void* event) -> Eina_Bool { - auto* self = reinterpret_cast(data); - if (self->view_) { - auto* key_event = reinterpret_cast(event); - if (key_event->window == self->GetWindowId()) { - self->view_->OnKey(key_event, false); - return ECORE_CALLBACK_DONE; - } + evas_object_callbacks_[EVAS_CALLBACK_KEY_DOWN] = [](void* data, Evas* evas, + Evas_Object* object, + void* event_info) { + auto* self = reinterpret_cast(data); + if (self->view_) { + if (self->elm_win_ == object) { + auto* key_event = reinterpret_cast(event_info); + int handled = false; + if (self->input_method_context_->IsInputPanelShown()) { + handled = + self->input_method_context_->HandleEvasEventKeyDown(key_event); + } + if (!handled) { + self->view_->OnKey( + key_event->key, key_event->string, key_event->compose, + EvasModifierToEcoreEventModifiers(key_event->modifiers), + key_event->keycode, true); } - return ECORE_CALLBACK_PASS_ON; - }, - this)); + } + } + }; + evas_object_event_callback_add(elm_win_, EVAS_CALLBACK_KEY_DOWN, + evas_object_callbacks_[EVAS_CALLBACK_KEY_DOWN], + this); - ecore_event_key_handlers_.push_back(ecore_event_handler_add( - ECORE_EVENT_KEY_UP, - [](void* data, int type, void* event) -> Eina_Bool { + evas_object_callbacks_[EVAS_CALLBACK_KEY_UP] = + [](void* data, Evas* evas, Evas_Object* object, void* event_info) { auto* self = reinterpret_cast(data); if (self->view_) { - auto* key_event = reinterpret_cast(event); - if (key_event->window == self->GetWindowId()) { - self->view_->OnKey(key_event, true); - return ECORE_CALLBACK_DONE; + if (self->elm_win_ == object) { + auto* key_event = reinterpret_cast(event_info); + int handled = false; + if (self->input_method_context_->IsInputPanelShown()) { + handled = + self->input_method_context_->HandleEvasEventKeyUp(key_event); + } + if (!handled) { + self->view_->OnKey( + key_event->key, key_event->string, key_event->compose, + EvasModifierToEcoreEventModifiers(key_event->modifiers), + key_event->keycode, false); + } } } - return ECORE_CALLBACK_PASS_ON; - }, - this)); + }; + evas_object_event_callback_add(elm_win_, EVAS_CALLBACK_KEY_UP, + evas_object_callbacks_[EVAS_CALLBACK_KEY_UP], + this); } void TizenWindowElementary::UnregisterEventHandlers() { evas_object_smart_callback_del(elm_win_, "rotation,changed", - rotatoin_changed_callback_); + rotation_changed_callback_); evas_object_event_callback_del( elm_win_, EVAS_CALLBACK_MOUSE_DOWN, @@ -265,11 +298,11 @@ void TizenWindowElementary::UnregisterEventHandlers() { evas_object_event_callback_del( elm_win_, EVAS_CALLBACK_MOUSE_WHEEL, evas_object_callbacks_[EVAS_CALLBACK_MOUSE_WHEEL]); - - for (Ecore_Event_Handler* handler : ecore_event_key_handlers_) { - ecore_event_handler_del(handler); - } - ecore_event_key_handlers_.clear(); + evas_object_event_callback_del( + elm_win_, EVAS_CALLBACK_KEY_DOWN, + evas_object_callbacks_[EVAS_CALLBACK_KEY_DOWN]); + evas_object_event_callback_del(elm_win_, EVAS_CALLBACK_KEY_UP, + evas_object_callbacks_[EVAS_CALLBACK_KEY_UP]); } TizenWindow::Geometry TizenWindowElementary::GetWindowGeometry() { @@ -345,4 +378,20 @@ void TizenWindowElementary::OnGeometryChanged(Geometry geometry) { view_->OnResize(geometry.left, geometry.top, geometry.width, geometry.height); } +void TizenWindowElementary::PrepareInputMethod() { + input_method_context_ = + std::make_unique(GetWindowId()); + + // Set input method callbacks. + input_method_context_->SetOnPreeditStart( + [this]() { view_->OnComposeBegin(); }); + input_method_context_->SetOnPreeditChanged( + [this](std::string str, int cursor_pos) { + view_->OnComposeChange(str, cursor_pos); + }); + input_method_context_->SetOnPreeditEnd([this]() { view_->OnComposeEnd(); }); + input_method_context_->SetOnCommit( + [this](std::string str) { view_->OnCommit(str); }); +} + } // namespace flutter diff --git a/shell/platform/tizen/tizen_window_elementary.h b/shell/platform/tizen/tizen_window_elementary.h index 930cdc5c2f0ec..ac3fa9fcb4aeb 100644 --- a/shell/platform/tizen/tizen_window_elementary.h +++ b/shell/platform/tizen/tizen_window_elementary.h @@ -8,8 +8,6 @@ #include "flutter/shell/platform/tizen/tizen_window.h" -#define EFL_BETA_API_SUPPORT -#include #include #include @@ -65,13 +63,14 @@ class TizenWindowElementary : public TizenWindow { void UnregisterEventHandlers(); + void PrepareInputMethod(); + Evas_Object* elm_win_ = nullptr; Evas_Object* image_ = nullptr; - Evas_Smart_Cb rotatoin_changed_callback_; + Evas_Smart_Cb rotation_changed_callback_; std::unordered_map evas_object_callbacks_; - std::vector ecore_event_key_handlers_; }; } // namespace flutter