Skip to content

Commit

Permalink
Handle key events for tizen webview (flutter-tizen#11)
Browse files Browse the repository at this point in the history
* Implement dispatchKeyDownEvent and dispatchKeyUpEvent
* Translate ecore key values to KeyValues for webview
  • Loading branch information
seungsoo47 authored and bwikbs committed Mar 26, 2021
1 parent c19cb9f commit a279e99
Show file tree
Hide file tree
Showing 5 changed files with 319 additions and 1 deletion.
6 changes: 5 additions & 1 deletion packages/webview_flutter/lib/webview_flutter_tizen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Binary file modified packages/webview_flutter/tizen/lib/liblightweight-web-engine.so
Binary file not shown.
Binary file not shown.
310 changes: 310 additions & 0 deletions packages/webview_flutter/tizen/src/webview.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#include "lwe/PlatformIntegrationData.h"
#include "webview_factory.h"

#include <Ecore_Input_Evas.h>
#include <Ecore_IMF_Evas.h>

std::string extractStringFromMap(const flutter::EncodableValue& arguments,
const char* key) {
if (std::holds_alternative<flutter::EncodableMap>(arguments)) {
Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 4 additions & 0 deletions packages/webview_flutter/tizen/src/webview.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<flutter::EncodableValue>& method_call,
Expand Down

0 comments on commit a279e99

Please sign in to comment.