diff --git a/packages/webview_flutter/lib/webview_flutter_tizen.dart b/packages/webview_flutter/lib/webview_flutter_tizen.dart index a8b507c64..26a276708 100644 --- a/packages/webview_flutter/lib/webview_flutter_tizen.dart +++ b/packages/webview_flutter/lib/webview_flutter_tizen.dart @@ -275,7 +275,11 @@ class PlatformViewsServiceTizen { case 'viewFocused': final int id = call.arguments as int; if (_focusCallbacks.containsKey(id)) { - _focusCallbacks[id](); + if (_focusCallbacks[id] != null) { + _focusCallbacks[id](); + } else { + throw FlutterError('FocusCallbacks[$id] must not be null.'); + } } break; default: diff --git a/packages/webview_flutter/tizen/lib/liblightweight-web-engine.so b/packages/webview_flutter/tizen/lib/liblightweight-web-engine.so index a85c1b917..8057f6168 100644 Binary files a/packages/webview_flutter/tizen/lib/liblightweight-web-engine.so and b/packages/webview_flutter/tizen/lib/liblightweight-web-engine.so differ diff --git a/packages/webview_flutter/tizen/liblightweight-web-engine.so b/packages/webview_flutter/tizen/liblightweight-web-engine.so deleted file mode 100644 index a85c1b917..000000000 Binary files a/packages/webview_flutter/tizen/liblightweight-web-engine.so and /dev/null differ diff --git a/packages/webview_flutter/tizen/src/webview.cc b/packages/webview_flutter/tizen/src/webview.cc index 62ad2972a..922f03378 100644 --- a/packages/webview_flutter/tizen/src/webview.cc +++ b/packages/webview_flutter/tizen/src/webview.cc @@ -18,6 +18,9 @@ #include "lwe/PlatformIntegrationData.h" #include "webview_factory.h" +#include +#include + std::string extractStringFromMap(const flutter::EncodableValue& arguments, const char* key) { if (std::holds_alternative(arguments)) { @@ -114,6 +117,313 @@ void WebView::touch(int type, int button, double x, double y, double dx, } } +static LWE::KeyValue ecoreEventKeyToKeyValue(const char* ecoreKeyString, + bool isShiftPressed) { + if (strcmp("Left", ecoreKeyString) == 0) { + return LWE::KeyValue::ArrowLeftKey; + } else if (strcmp("Right", ecoreKeyString) == 0) { + return LWE::KeyValue::ArrowRightKey; + } else if (strcmp("Up", ecoreKeyString) == 0) { + return LWE::KeyValue::ArrowUpKey; + } else if (strcmp("Down", ecoreKeyString) == 0) { + return LWE::KeyValue::ArrowDownKey; + } else if (strcmp("space", ecoreKeyString) == 0) { + return LWE::KeyValue::SpaceKey; + } else if (strcmp("Return", ecoreKeyString) == 0) { + return LWE::KeyValue::EnterKey; + } else if (strcmp("Tab", ecoreKeyString) == 0) { + return LWE::KeyValue::TabKey; + } else if (strcmp("BackSpace", ecoreKeyString) == 0) { + return LWE::KeyValue::BackspaceKey; + } else if (strcmp("Escape", ecoreKeyString) == 0) { + return LWE::KeyValue::EscapeKey; + } else if (strcmp("Delete", ecoreKeyString) == 0) { + return LWE::KeyValue::DeleteKey; + } else if (strcmp("at", ecoreKeyString) == 0) { + return LWE::KeyValue::AtMarkKey; + } else if (strcmp("minus", ecoreKeyString) == 0) { + if (isShiftPressed) { + return LWE::KeyValue::UnderScoreMarkKey; + } else { + return LWE::KeyValue::MinusMarkKey; + } + } else if (strcmp("equal", ecoreKeyString) == 0) { + if (isShiftPressed) { + return LWE::KeyValue::PlusMarkKey; + } else { + return LWE::KeyValue::EqualitySignKey; + } + } else if (strcmp("bracketleft", ecoreKeyString) == 0) { + if (isShiftPressed) { + return LWE::KeyValue::LeftCurlyBracketMarkKey; + } else { + return LWE::KeyValue::LeftSquareBracketKey; + } + } else if (strcmp("bracketright", ecoreKeyString) == 0) { + if (isShiftPressed) { + return LWE::KeyValue::RightCurlyBracketMarkKey; + } else { + return LWE::KeyValue::RightSquareBracketKey; + } + } else if (strcmp("semicolon", ecoreKeyString) == 0) { + if (isShiftPressed) { + return LWE::KeyValue::ColonMarkKey; + } else { + return LWE::KeyValue::SemiColonMarkKey; + } + } else if (strcmp("apostrophe", ecoreKeyString) == 0) { + if (isShiftPressed) { + return LWE::KeyValue::DoubleQuoteMarkKey; + } else { + return LWE::KeyValue::SingleQuoteMarkKey; + } + } else if (strcmp("comma", ecoreKeyString) == 0) { + if (isShiftPressed) { + return LWE::KeyValue::LessThanMarkKey; + } else { + return LWE::KeyValue::CommaMarkKey; + } + } else if (strcmp("period", ecoreKeyString) == 0) { + if (isShiftPressed) { + return LWE::KeyValue::GreaterThanSignKey; + } else { + return LWE::KeyValue::PeriodKey; + } + } else if (strcmp("slash", ecoreKeyString) == 0) { + if (isShiftPressed) { + return LWE::KeyValue::QuestionMarkKey; + } else { + return LWE::KeyValue::SlashKey; + } + } else if (strlen(ecoreKeyString) == 1) { + char ch = ecoreKeyString[0]; + if (ch >= '0' && ch <= '9') { + if (isShiftPressed) { + switch (ch) { + case '1': + return LWE::KeyValue::ExclamationMarkKey; + case '2': + return LWE::KeyValue::AtMarkKey; + case '3': + return LWE::KeyValue::SharpMarkKey; + case '4': + return LWE::KeyValue::DollarMarkKey; + case '5': + return LWE::KeyValue::PercentMarkKey; + case '6': + return LWE::KeyValue::CaretMarkKey; + case '7': + return LWE::KeyValue::AmpersandMarkKey; + case '8': + return LWE::KeyValue::AsteriskMarkKey; + case '9': + return LWE::KeyValue::LeftParenthesisMarkKey; + case '0': + return LWE::KeyValue::RightParenthesisMarkKey; + } + } + return (LWE::KeyValue)(LWE::KeyValue::Digit0Key + ch - '0'); + } else if (ch >= 'a' && ch <= 'z') { + return (LWE::KeyValue)(LWE::KeyValue::LowerAKey + ch - 'a'); + } else if (ch >= 'A' && ch <= 'Z') { + return (LWE::KeyValue)(LWE::KeyValue::AKey + ch - 'A'); + } + } else if (strcmp("XF86AudioRaiseVolume", ecoreKeyString) == 0) { + return LWE::KeyValue::TVVolumeUpKey; + } else if (strcmp("XF86AudioLowerVolume", ecoreKeyString) == 0) { + return LWE::KeyValue::TVVolumeDownKey; + } else if (strcmp("XF86AudioMute", ecoreKeyString) == 0) { + return LWE::KeyValue::TVMuteKey; + } else if (strcmp("XF86RaiseChannel", ecoreKeyString) == 0) { + return LWE::KeyValue::TVChannelUpKey; + } else if (strcmp("XF86LowerChannel", ecoreKeyString) == 0) { + return LWE::KeyValue::TVChannelDownKey; + } else if (strcmp("XF86AudioRewind", ecoreKeyString) == 0) { + return LWE::KeyValue::MediaTrackPreviousKey; + } else if (strcmp("XF86AudioNext", ecoreKeyString) == 0) { + return LWE::KeyValue::MediaTrackNextKey; + } else if (strcmp("XF86AudioPause", ecoreKeyString) == 0) { + return LWE::KeyValue::MediaPauseKey; + } else if (strcmp("XF86AudioRecord", ecoreKeyString) == 0) { + return LWE::KeyValue::MediaRecordKey; + } else if (strcmp("XF86AudioPlay", ecoreKeyString) == 0) { + return LWE::KeyValue::MediaPlayKey; + } else if (strcmp("XF86AudioStop", ecoreKeyString) == 0) { + return LWE::KeyValue::MediaStopKey; + } else if (strcmp("XF86Info", ecoreKeyString) == 0) { + return LWE::KeyValue::TVInfoKey; + } else if (strcmp("XF86Back", ecoreKeyString) == 0) { + return LWE::KeyValue::TVReturnKey; + } else if (strcmp("XF86Red", ecoreKeyString) == 0) { + return LWE::KeyValue::TVRedKey; + } else if (strcmp("XF86Green", ecoreKeyString) == 0) { + return LWE::KeyValue::TVGreenKey; + } else if (strcmp("XF86Yellow", ecoreKeyString) == 0) { + return LWE::KeyValue::TVYellowKey; + } else if (strcmp("XF86Blue", ecoreKeyString) == 0) { + return LWE::KeyValue::TVBlueKey; + } else if (strcmp("XF86SysMenu", ecoreKeyString) == 0) { + return LWE::KeyValue::TVMenuKey; + } else if (strcmp("XF86Home", ecoreKeyString) == 0) { + return LWE::KeyValue::TVHomeKey; + } else if (strcmp("XF86Exit", ecoreKeyString) == 0) { + return LWE::KeyValue::TVExitKey; + } else if (strcmp("XF86PreviousChannel", ecoreKeyString) == 0) { + return LWE::KeyValue::TVPreviousChannel; + } else if (strcmp("XF86ChannelList", ecoreKeyString) == 0) { + return LWE::KeyValue::TVChannelList; + } else if (strcmp("XF86ChannelGuide", ecoreKeyString) == 0) { + return LWE::KeyValue::TVChannelGuide; + } else if (strcmp("XF86SimpleMenu", ecoreKeyString) == 0) { + return LWE::KeyValue::TVSimpleMenu; + } else if (strcmp("XF86EManual", ecoreKeyString) == 0) { + return LWE::KeyValue::TVEManual; + } else if (strcmp("XF86ExtraApp", ecoreKeyString) == 0) { + return LWE::KeyValue::TVExtraApp; + } else if (strcmp("XF86Search", ecoreKeyString) == 0) { + return LWE::KeyValue::TVSearch; + } else if (strcmp("XF86PictureSize", ecoreKeyString) == 0) { + return LWE::KeyValue::TVPictureSize; + } else if (strcmp("XF86Sleep", ecoreKeyString) == 0) { + return LWE::KeyValue::TVSleep; + } else if (strcmp("XF86Caption", ecoreKeyString) == 0) { + return LWE::KeyValue::TVCaption; + } else if (strcmp("XF86More", ecoreKeyString) == 0) { + return LWE::KeyValue::TVMore; + } else if (strcmp("XF86BTVoice", ecoreKeyString) == 0) { + return LWE::KeyValue::TVBTVoice; + } else if (strcmp("XF86Color", ecoreKeyString) == 0) { + return LWE::KeyValue::TVColor; + } else if (strcmp("XF86PlayBack", ecoreKeyString) == 0) { + return LWE::KeyValue::TVPlayBack; + } + + LOG_DEBUG("WebViewEFL - unimplemented key %s\n", ecoreKeyString); + return LWE::KeyValue::UnidentifiedKey; +} + +void WebView::dispatchKeyDownEvent(Ecore_Event_Key* keyEvent) { + std::string keyName = keyEvent->keyname; + LOG_DEBUG("ECORE_EVENT_KEY_DOWN [%s, %d]\n", keyName.data(), + (keyEvent->modifiers & 1) || (keyEvent->modifiers & 2)); + + bool lastInputTimeWasZeroBefore = false; + // if (webViewInstance_->m_lastInputTime == 0) { + // lastInputTimeWasZeroBefore = true; + // webViewInstance_->m_lastInputTime = Starfish::longTickCount(); + // } + + if (!isFocused()) { + LOG_DEBUG("ignore keydown because we dont have focus"); + return; + } + +#ifdef TV_PROFILE + if ((strncmp(keyName.data(), "XF86Back", 8) == 0)) { + keyName = "Escape"; + } +#endif + + if ((strcmp(keyName.data(), "XF86Exit") == 0) || + (strcmp(keyName.data(), "Select") == 0) || + (strcmp(keyName.data(), "Cancel") == 0)) { + if (strcmp(keyName.data(), "Select") == 0) { + webViewInstance_->AddIdleCallback( + [](void* data) { + LWE::WebContainer* self = (LWE::WebContainer*)data; + LWE::KeyValue kv = LWE::KeyValue::EnterKey; + self->DispatchKeyDownEvent(kv); + self->DispatchKeyPressEvent(kv); + self->DispatchKeyUpEvent(kv); + // self->HideSoftwareKeyboardIfPossible(); + }, + webViewInstance_); + } else { + webViewInstance_->AddIdleCallback( + [](void* data) { + LWE::WebContainer* self = (LWE::WebContainer*)data; + // self->HideSoftwareKeyboardIfPossible(); + }, + webViewInstance_); + } + } + + auto keyValue = ecoreEventKeyToKeyValue(keyName.data(), false); + + // if (keyValue >= LWE::KeyValue::ArrowDownKey && + // keyValue <= LWE::KeyValue::ArrowRightKey) { + // int currentTimestamp = keyEvent->timestamp; + // if (currentTimestamp - + // g_arrowKeyDownTimestamp[keyValue - LWE::KeyValue::ArrowDownKey] < + // g_arrowKeyDownMinimumDelayInMS) { + // return; + // } + // g_arrowKeyDownTimestamp[keyValue - LWE::KeyValue::ArrowDownKey] = + // currentTimestamp; + // } + + if (lastInputTimeWasZeroBefore) { + webViewInstance_->DispatchKeyDownEvent(keyValue); + webViewInstance_->DispatchKeyPressEvent(keyValue); + } else { + struct Param { + LWE::WebContainer* webViewInstance; + LWE::KeyValue keyValue; + }; + Param* p = new Param(); + p->webViewInstance = webViewInstance_; + p->keyValue = keyValue; + + webViewInstance_->AddIdleCallback( + [](void* data) { + Param* p = (Param*)data; + p->webViewInstance->DispatchKeyDownEvent(p->keyValue); + p->webViewInstance->DispatchKeyPressEvent(p->keyValue); + delete p; + }, + p); + } +} + +void WebView::dispatchKeyUpEvent(Ecore_Event_Key* keyEvent) { + std::string keyName = keyEvent->keyname; + LOG_DEBUG("ECORE_EVENT_KEY_UP [%s, %d]\n", keyName.data(), + (keyEvent->modifiers & 1) || (keyEvent->modifiers & 2)); + + if (!isFocused()) { + LOG_DEBUG("ignore keyup because we dont have focus"); + return; + } + +#ifdef TV_PROFILE + if ((strncmp(keyName.data(), "XF86Back", 8) == 0)) { + keyName = "Escape"; + } +#endif + auto keyValue = ecoreEventKeyToKeyValue(keyName.data(), false); + + // if (keyValue >= LWE::KeyValue::ArrowDownKey && + // keyValue <= LWE::KeyValue::ArrowRightKey) { + // g_arrowKeyDownTimestamp[keyValue - LWE::KeyValue::ArrowDownKey] = 0; + // } + + struct Param { + LWE::WebContainer* webView; + LWE::KeyValue keyValue; + }; + Param* p = new Param(); + p->webView = webViewInstance_; + p->keyValue = keyValue; + + webViewInstance_->AddIdleCallback( + [](void* data) { + Param* p = (Param*)data; + p->webView->DispatchKeyUpEvent(p->keyValue); + delete p; + }, + p); +} + void WebView::clearFocus() { LOG_DEBUG("WebView::clearFocus \n"); } void WebView::setDirection(int direction) { diff --git a/packages/webview_flutter/tizen/src/webview.h b/packages/webview_flutter/tizen/src/webview.h index 92077c211..3d4d178ab 100644 --- a/packages/webview_flutter/tizen/src/webview.h +++ b/packages/webview_flutter/tizen/src/webview.h @@ -24,6 +24,10 @@ class WebView : public PlatformView { virtual void setDirection(int direction) override; virtual void clearFocus() override; + // Key input event + virtual void dispatchKeyDownEvent(Ecore_Event_Key* key) override; + virtual void dispatchKeyUpEvent(Ecore_Event_Key* key) override; + private: void HandleMethodCall( const flutter::MethodCall& method_call,