1 // Copyright 2021 Samsung Electronics. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/ozone/platform/efl/efl_event_handler.h"
6 #include "ui/display/screen.h"
8 #include "base/logging.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "build/build_config.h"
12 #include "tizen/system_info.h"
13 #include "ui/base/ime/linux/linux_input_method_context_factory.h"
14 #include "ui/events/base_event_utils.h"
15 #include "ui/events/event.h"
16 #include "ui/events/types/event_type.h"
17 #include "ui/gfx/geometry/point_f.h"
18 #include "ui/ozone/platform/efl/efl_keycode_map.h"
19 #include "ui/ozone/platform/efl/efl_platform_event_source.h"
20 #include "ui/ozone/platform/efl/efl_window.h"
21 #include "ui/ozone/platform/efl/im_context_efl.h"
23 #if BUILDFLAG(IS_TIZEN)
24 #include "ui/events/keycodes/dom/dom_code.h"
25 #include "ui/events/keycodes/dom/dom_key.h"
26 #include "ui/events/keycodes/dom/keycode_converter.h"
27 #include "ui/events/keycodes/keyboard_code_conversion.h"
30 #if BUILDFLAG(IS_TIZEN_TV)
31 #include "base/base_switches.h"
32 #include "base/command_line.h"
33 #include "third_party/blink/public/platform/web_application_type.h"
39 const float kDefaultScrollStep = 20;
41 inline bool string_ends_with(std::string const& value,
42 std::string const& match) {
43 if (match.size() > value.size()) {
46 return std::equal(match.rbegin(), match.rend(), value.rbegin());
49 inline bool string_starts_with(std::string const& value,
50 std::string const& match) {
51 if (match.size() > value.size()) {
54 return std::equal(match.begin(), match.end(), value.begin());
58 const std::string kDeviceNameSmartView = "SMART_VIEW";
59 const std::string kDeviceNamePanelKey = "wt61p807 panel key device";
60 const std::string kDeviceNameRemote = "wt61p807 rc device";
61 const std::string kDeviceNameSmartRC = "Smart Control";
62 // To allow to receive Tomato send key events
63 const std::string kDeviceNameAutoModeDevice = "AUTO_MODE_DEVICE";
64 const std::string kDeviceNameIME = "ime";
66 bool IsRCDevice(Evas_Device_Class device_id, const std::string device_name) {
67 if (device_id == EVAS_DEVICE_CLASS_KEYBOARD) {
68 if (!device_name.compare(kDeviceNameRemote) ||
69 !device_name.compare(kDeviceNameSmartView) ||
70 !device_name.compare(kDeviceNamePanelKey) ||
71 !device_name.compare(kDeviceNameAutoModeDevice) ||
72 device_name.find(kDeviceNameSmartRC) != std::string::npos)
78 enum { kLeftButton = 1, kMiddleButton = 2, kRightButton = 3 };
80 EventFlags EvasToUIMouseButton(int button) {
81 if (button == kLeftButton)
82 return EF_LEFT_MOUSE_BUTTON;
83 if (button == kMiddleButton)
84 return EF_MIDDLE_MOUSE_BUTTON;
85 if (button == kRightButton)
86 return EF_RIGHT_MOUSE_BUTTON;
91 int GetEventFlagsFromKey(const char* key) {
93 if (base::StartsWith(key, "Shift", base::CompareCase::SENSITIVE))
94 flags |= EF_SHIFT_DOWN;
95 if (base::StartsWith(key, "Control", base::CompareCase::SENSITIVE))
96 flags |= EF_CONTROL_DOWN;
97 if (base::StartsWith(key, "Alt", base::CompareCase::SENSITIVE))
99 if (base::StartsWith(key, "Meta", base::CompareCase::SENSITIVE))
100 flags |= EF_COMMAND_DOWN;
101 if (base::StartsWith(key, "Super", base::CompareCase::SENSITIVE))
102 flags |= EF_COMMAND_DOWN;
107 int EvasModifiersToEventFlags(const Evas_Modifier* modifiers,
108 bool check_super = true) {
110 if (evas_key_modifier_is_set(modifiers, "Shift"))
111 flags |= EF_SHIFT_DOWN;
112 if (evas_key_modifier_is_set(modifiers, "Control"))
113 flags |= EF_CONTROL_DOWN;
114 if (evas_key_modifier_is_set(modifiers, "Alt"))
115 flags |= EF_ALT_DOWN;
116 if (evas_key_modifier_is_set(modifiers, "Meta"))
117 flags |= EF_COMMAND_DOWN;
118 if (evas_key_modifier_is_set(modifiers, "Super") && check_super)
119 flags |= EF_COMMAND_DOWN;
124 static EventType EvasTouchEventTypeToUI(Evas_Touch_Point_State evas_touch) {
125 switch (evas_touch) {
126 case EVAS_TOUCH_POINT_DOWN:
127 return ET_TOUCH_PRESSED;
128 case EVAS_TOUCH_POINT_MOVE:
129 return ET_TOUCH_MOVED;
130 case EVAS_TOUCH_POINT_UP:
131 return ET_TOUCH_RELEASED;
132 case EVAS_TOUCH_POINT_CANCEL:
133 return ET_TOUCH_CANCELLED;
134 case EVAS_TOUCH_POINT_STILL:
135 // Not handled by chromium, should not be passed here.
142 float GetDeviceScaleFactor() {
143 static float device_scale_factor = 0.0f;
144 if (!device_scale_factor) {
145 device_scale_factor =
146 display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
148 return device_scale_factor;
153 EflEventHandler::EflEventHandler(EflWindow* window)
154 : window_(window), events_overlay_(window->native_view()) {
155 if (IsMobileProfile())
156 touch_events_enabled_ = true;
161 EflEventHandler::~EflEventHandler() {
162 if (mouse_events_enabled_)
163 DeleteMouseCallbacks();
165 if (key_events_enabled_)
166 DeleteKeyCallbacks();
168 if (touch_events_enabled_)
169 DeleteTouchCallbacks();
172 void EflEventHandler::RegisterCallbacks() {
173 if (mouse_events_enabled_)
176 if (key_events_enabled_)
179 #if BUILDFLAG(IS_TIZEN_TV)
180 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
181 switches::kEnableOffscreenRendering))
183 evas_object_focus_set(events_overlay_, EINA_TRUE);
185 if (touch_events_enabled_)
189 int EflEventHandler::GetTopControlsHeight() {
190 int top_controls_height = 0;
191 evas_object_geometry_get(events_overlay_, nullptr, &top_controls_height,
193 return top_controls_height;
196 template <typename EVT>
197 bool EflEventHandler::GetTouchEventsEnabled(const EVT* evas_evt) {
198 #if BUILDFLAG(IS_TIZEN_TV)
199 return (touch_events_enabled_ &&
200 evas_device_class_get(evas_evt->dev) == EVAS_DEVICE_CLASS_TOUCH);
202 return touch_events_enabled_;
206 MouseEvent MakeWebMouseEvent(EventType type, const EVT* ev, int delta_y) {
207 gfx::PointF location(ev->canvas.x, ev->canvas.y);
208 location.Offset(0, -delta_y);
209 int button = EvasToUIMouseButton(ev->button);
210 int event_flags = EvasModifiersToEventFlags(ev->modifiers);
211 event_flags |= button;
212 MouseEvent event(type, location, location, base::TimeTicks::Now(),
213 event_flags, button);
215 #if BUILDFLAG(IS_TIZEN_TV)
217 if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK) // dblclick
219 if (ev->flags & EVAS_BUTTON_TRIPLE_CLICK) // triple click
222 event.SetClickCount(clickCount);
228 TouchEvent MakeTouchEvent(Evas_Coord_Point pt,
229 Evas_Touch_Point_State state,
231 unsigned int timestamp,
233 base::TimeTicks event_timestamp = base::TimeTicks::FromInternalValue(
234 timestamp * base::Time::kMicrosecondsPerMillisecond);
237 event_timestamp = EventTimeForNow();
241 TouchEvent touch_event(
242 EvasTouchEventTypeToUI(state), gfx::Point(), event_timestamp,
243 PointerDetails(EventPointerType::kTouch, id, 0.0f, 0.0f, 0.0f));
244 gfx::PointF point(pt.x, pt.y);
245 touch_event.set_location_f(point);
246 touch_event.set_root_location_f(point);
251 KeyEvent MakeWebKeyEvent(bool pressed, const EVT* evt) {
252 EventType type = pressed ? ET_KEY_PRESSED : ET_KEY_RELEASED;
253 int native_key_code = evt->keycode;
254 KeyboardCode windows_key_code = UIKeyCodeFromEflKey(evt->key);
257 #if BUILDFLAG(IS_TIZEN_TV)
258 // On combinate key "shift+Alt+xxx", the "key" of the "Alt" is
259 // "Meta_L/Meta_R", not the "Alt_L/Alt_R", so use the keyname replace the
260 // "key" to get the flag.
262 flags = GetEventFlagsFromKey(evt->keyname);
265 flags = GetEventFlagsFromKey(evt->key);
267 int key_modifiers = 0;
268 if (evas_key_lock_is_set(evt->locks, "Caps_Lock"))
269 key_modifiers |= EF_CAPS_LOCK_ON;
271 key_modifiers |= EvasModifiersToEventFlags(evt->modifiers);
273 // For Modifiers Key, need set the modifier when key press,
274 // no need set the modifier when key release.
275 // refer w3c spec: https://w3c.github.io/uievents/#keys-modifierss
277 key_modifiers |= flags;
279 key_modifiers &= ~flags;
281 #if BUILDFLAG(IS_TIZEN)
282 DomCode domCode = KeycodeConverter::NativeKeycodeToDomCode(native_key_code);
284 DomKey domKey = KeycodeConverter::KeyStringToDomKey(evt->key);
285 // If the efl key name is not identified, use its domcode to find it in domkey
287 if ((domKey == DomKey::NONE) && (domCode != DomCode::NONE)) {
288 int flags = key_modifiers;
289 KeyboardCode windowsKeyCode = VKEY_UNKNOWN;
291 DomCodeToUsLayoutDomKey(domCode, flags, &domKey, &windowsKeyCode);
294 KeyEvent event(type, windows_key_code, domCode, key_modifiers, domKey,
295 base::TimeTicks::Now(), false);
296 #if BUILDFLAG(IS_TIZEN_TV)
297 const char* device_name = evas_device_name_get(evt->dev);
299 // We need distinguish if key is from RC in render process
300 if (IsRCDevice(evas_device_class_get(evt->dev), device_name))
301 event.is_from_rc = true;
303 // Add device name property in keyboard event.
304 event.device_name = device_name;
309 KeyEvent event(type, windows_key_code, key_modifiers, base::TimeTicks::Now());
315 template KeyEvent MakeWebKeyEvent(bool, const Evas_Event_Key_Down*);
316 template KeyEvent MakeWebKeyEvent(bool, const Evas_Event_Key_Up*);
318 void EflEventHandler::SetMouseEventsEnabled(bool enabled) {
319 if (mouse_events_enabled_ == enabled)
322 mouse_events_enabled_ = enabled;
324 LOG(INFO) << "SetMouseEventsEnabled: " << (enabled ? "enabled" : "disabled");
328 DeleteMouseCallbacks();
331 void EflEventHandler::SetTouchEventsEnabled(bool enabled) {
332 if (touch_events_enabled_ == enabled)
335 touch_events_enabled_ = enabled;
337 LOG(INFO) << "SetTouchEventsEnabled: " << (enabled ? "enabled" : "disabled");
341 DeleteTouchCallbacks();
344 void EflEventHandler::SetKeyEventsEnabled(bool enabled) {
345 if (key_events_enabled_ == enabled)
348 key_events_enabled_ = enabled;
350 LOG(INFO) << "SetKeyEventsEnabled: " << (enabled ? "enabled" : "disabled");
354 DeleteKeyCallbacks();
357 void EflEventHandler::SendKeyEvent(Evas_Object* ewk_view,
361 OnKeyDown(static_cast<void*>(this), nullptr, ewk_view, event_info);
363 OnKeyUp(static_cast<void*>(this), nullptr, ewk_view, event_info);
367 static int mouse_pre_x = 0;
368 static int mouse_pre_y = 0;
370 void EflEventHandler::SendMouseDown(int button, int x, int y) {
371 Evas_Event_Mouse_Down ev;
373 ev.flags = EVAS_BUTTON_NONE;
377 ev.timestamp = ecore_time_get();
379 OnMouseDown(static_cast<void*>(this), window_->evas(), events_overlay_, &ev);
382 void EflEventHandler::SendMouseUp(int button, int x, int y) {
383 Evas_Event_Mouse_Up ev;
385 ev.flags = EVAS_BUTTON_NONE;
389 ev.timestamp = ecore_time_get();
391 OnMouseUp(static_cast<void*>(this), window_->evas(), events_overlay_, &ev);
394 void EflEventHandler::SendMouseMove(int x, int y) {
395 Evas_Event_Mouse_Move ev;
399 ev.prev.canvas.x = mouse_pre_x;
400 ev.prev.canvas.y = mouse_pre_y;
402 ev.timestamp = ecore_time_get();
404 OnMouseMove(static_cast<void*>(this), window_->evas(), events_overlay_, &ev);
410 void EflEventHandler::SendMouseWheel(bool y_direction, int step, int x, int y) {
411 Evas_Event_Mouse_Wheel ev;
412 ev.direction = y_direction ? 0 : 1;
417 ev.timestamp = ecore_time_get();
419 OnMouseWheel(static_cast<void*>(this), window_->evas(), events_overlay_, &ev);
422 void EflEventHandler::SendMouseIn() {
423 OnMouseIn(static_cast<void*>(this), nullptr, nullptr, nullptr);
426 void EflEventHandler::SendMouseOut() {
427 Evas_Event_Mouse_Out ev;
429 ev.canvas.x = mouse_pre_x;
430 ev.canvas.y = mouse_pre_y;
432 ev.timestamp = ecore_time_get();
434 OnMouseOut(static_cast<void*>(this), window_->evas(), events_overlay_, &ev);
437 void EflEventHandler::AddMouseCallbacks() {
438 evas_object_event_callback_add(events_overlay_, EVAS_CALLBACK_MOUSE_DOWN,
440 evas_object_event_callback_add(events_overlay_, EVAS_CALLBACK_MOUSE_UP,
442 evas_object_event_callback_add(events_overlay_, EVAS_CALLBACK_MOUSE_MOVE,
444 evas_object_event_callback_add(events_overlay_, EVAS_CALLBACK_MOUSE_IN,
446 evas_object_event_callback_add(events_overlay_, EVAS_CALLBACK_MOUSE_OUT,
448 evas_object_event_callback_add(events_overlay_, EVAS_CALLBACK_MOUSE_WHEEL,
452 void EflEventHandler::DeleteMouseCallbacks() {
453 evas_object_event_callback_del(events_overlay_, EVAS_CALLBACK_MOUSE_DOWN,
455 evas_object_event_callback_del(events_overlay_, EVAS_CALLBACK_MOUSE_UP,
457 evas_object_event_callback_del(events_overlay_, EVAS_CALLBACK_MOUSE_MOVE,
459 evas_object_event_callback_del(events_overlay_, EVAS_CALLBACK_MOUSE_IN,
461 evas_object_event_callback_del(events_overlay_, EVAS_CALLBACK_MOUSE_OUT,
463 evas_object_event_callback_del(events_overlay_, EVAS_CALLBACK_MOUSE_WHEEL,
467 void EflEventHandler::AddTouchCallbacks() {
468 evas_object_event_callback_add(events_overlay_, EVAS_CALLBACK_MULTI_DOWN,
469 OnMultiTouchDownEvent, this);
470 evas_object_event_callback_add(events_overlay_, EVAS_CALLBACK_MULTI_MOVE,
471 OnMultiTouchMoveEvent, this);
472 evas_object_event_callback_add(events_overlay_, EVAS_CALLBACK_MULTI_UP,
473 OnMultiTouchUpEvent, this);
476 void EflEventHandler::DeleteTouchCallbacks() {
477 evas_object_event_callback_del(events_overlay_, EVAS_CALLBACK_MULTI_DOWN,
478 OnMultiTouchDownEvent);
479 evas_object_event_callback_del(events_overlay_, EVAS_CALLBACK_MULTI_MOVE,
480 OnMultiTouchMoveEvent);
481 evas_object_event_callback_del(events_overlay_, EVAS_CALLBACK_MULTI_UP,
482 OnMultiTouchUpEvent);
485 void EflEventHandler::AddKeyCallbacks() {
486 evas_object_event_callback_add(events_overlay_, EVAS_CALLBACK_KEY_DOWN,
488 evas_object_event_callback_add(events_overlay_, EVAS_CALLBACK_KEY_UP, OnKeyUp,
492 void EflEventHandler::DeleteKeyCallbacks() {
493 evas_object_event_callback_del(events_overlay_, EVAS_CALLBACK_KEY_DOWN,
495 evas_object_event_callback_del(events_overlay_, EVAS_CALLBACK_KEY_UP,
500 void EflEventHandler::OnMouseDown(void* data,
504 EflEventHandler* thiz = static_cast<EflEventHandler*>(data);
505 Evas_Event_Mouse_Down* ev = static_cast<Evas_Event_Mouse_Down*>(event_info);
506 LOG(INFO) << "OnMouseDown";
508 thiz->window_->UpdateFocus(true);
510 if (thiz->GetTouchEventsEnabled(ev)) {
511 thiz->ProcessTouchEvents(ev->timestamp, false);
514 MakeWebMouseEvent(ET_MOUSE_PRESSED, ev, thiz->GetTopControlsHeight());
515 EflPlatformEventSource::GetInstance()->DispatchEflEvent(&event);
520 void EflEventHandler::OnMouseUp(void* data,
524 EflEventHandler* thiz = static_cast<EflEventHandler*>(data);
525 Evas_Event_Mouse_Up* ev = static_cast<Evas_Event_Mouse_Up*>(event_info);
526 LOG(INFO) << "OnMouseUp";
528 if (thiz->GetTouchEventsEnabled(ev)) {
529 thiz->ProcessTouchEvents(ev->timestamp, false);
532 MakeWebMouseEvent(ET_MOUSE_RELEASED, ev, thiz->GetTopControlsHeight());
533 EflPlatformEventSource::GetInstance()->DispatchEflEvent(&event);
538 void EflEventHandler::OnMouseMove(void* data,
542 EflEventHandler* thiz = static_cast<EflEventHandler*>(data);
544 Evas_Event_Mouse_Move* ev = static_cast<Evas_Event_Mouse_Move*>(event_info);
545 if (thiz->GetTouchEventsEnabled(ev)) {
546 thiz->ProcessTouchEvents(ev->timestamp, false);
548 gfx::PointF location(ev->cur.canvas.x, ev->cur.canvas.y);
549 location.Offset(0, -thiz->GetTopControlsHeight());
550 int button = EvasToUIMouseButton(ev->buttons);
551 int event_flags = EvasModifiersToEventFlags(ev->modifiers);
552 event_flags |= button;
553 MouseEvent event(ET_MOUSE_MOVED, location, location, base::TimeTicks::Now(),
554 event_flags, button);
555 const float sf = GetDeviceScaleFactor();
556 ui::MouseEvent::DispatcherApi(&event).set_movement(
557 gfx::Vector2dF((ev->cur.canvas.x / sf - ev->prev.canvas.x / sf),
558 (ev->cur.canvas.y / sf - ev->prev.canvas.y / sf)));
559 EflPlatformEventSource::GetInstance()->DispatchEflEvent(&event);
564 void EflEventHandler::OnMouseIn(void* data,
568 EflEventHandler* thiz = static_cast<EflEventHandler*>(data);
569 thiz->window_->UpdateFocus(true);
573 void EflEventHandler::OnMouseOut(void* data,
577 #if !BUILDFLAG(IS_TIZEN)
578 EflEventHandler* thiz = static_cast<EflEventHandler*>(data);
579 thiz->window_->UpdateFocus(false);
584 void EflEventHandler::OnMouseWheel(void* data,
588 Evas_Event_Mouse_Wheel* ev = static_cast<Evas_Event_Mouse_Wheel*>(event_info);
590 gfx::Vector2d offset;
592 offset.set_x(ev->z * kDefaultScrollStep);
594 offset.set_y(-(ev->z * kDefaultScrollStep));
596 gfx::PointF location(ev->canvas.x, ev->canvas.y);
597 int event_flags = EvasModifiersToEventFlags(ev->modifiers);
598 MouseWheelEvent event(offset, location, location, base::TimeTicks::Now(),
600 EflPlatformEventSource::GetInstance()->DispatchEflEvent(&event);
604 void EflEventHandler::OnKeyDown(void* data,
608 if (!obj || !event_info || !data)
611 Evas_Event_Key_Down* key_down = static_cast<Evas_Event_Key_Down*>(event_info);
612 EflEventHandler* thiz = static_cast<EflEventHandler*>(data);
613 LOG(INFO) << "OnKeyDown, key : " << key_down->key;
614 LOG(INFO) << "Before consumed check (Key Name: " << key_down->key
615 << ", Key State: Down)";
617 #if BUILDFLAG(IS_TIZEN_TV)
618 if (!thiz->key_event_checker_.is_null() &&
619 !thiz->key_event_checker_.Run(event_info, true)) {
624 #if BUILDFLAG(IS_TIZEN)
625 if (IsMobileProfile() || IsTvProfile()) {
626 if (thiz->FilterIMEKeyDownEvent(key_down)) {
627 LOG(INFO) << "OnKeyDown, IME filtered the key : " << key_down->key;
632 #if BUILDFLAG(IS_TIZEN_TV)
634 thiz->ConvertUpToReturnBackIfNeeded(key_down, true);
636 // In non webapp scene,"Cancel" key haven't added on the map,the keycode is
637 // 0. "Cancel" key is delivered by IME, for hiding IME panel,no need deliver
638 // the key event. Or else,the keycode 0 may exception handling by website.
639 if (!strcmp(key_down->key, "Cancel") && !blink::IsTIZENWRT())
644 KeyEvent event = MakeWebKeyEvent(true, key_down);
645 #if BUILDFLAG(IS_TIZEN_TV)
646 // Needed for HBBTV single window, multiwebview scenario.
647 event.SetDispatcher(thiz->window());
649 auto im_context_efl = thiz->GetIMContextEfl();
650 if (!im_context_efl ||
651 im_context_efl->ShouldHandleImmediately(key_down->key)) {
652 EflPlatformEventSource::GetInstance()->DispatchEflEvent(&event);
656 LOG(INFO) << "OnKeyUp,PushToKeyDownEventQueue,key:" << key_down->key;
657 im_context_efl->PushToKeyDownEventQueue(event);
661 void EflEventHandler::OnKeyUp(void* data,
665 if (!obj || !event_info || !data)
668 Evas_Event_Key_Up* key_up = static_cast<Evas_Event_Key_Up*>(event_info);
669 EflEventHandler* thiz = static_cast<EflEventHandler*>(data);
670 LOG(INFO) << "OnKeyUp, key : " << key_up->key;
671 LOG(INFO) << "Before consumed check (Key Name: " << key_up->key
672 << ", Key State: Up)";
674 #if BUILDFLAG(IS_TIZEN_TV)
675 if (!thiz->key_event_checker_.is_null() &&
676 !thiz->key_event_checker_.Run(event_info, false)) {
681 #if BUILDFLAG(IS_TIZEN)
682 if (IsMobileProfile() || IsTvProfile()) {
683 if (thiz->FilterIMEKeyUpEvent(key_up)) {
684 LOG(INFO) << "OnKeyUp, IME filtered the key : " << key_up->key;
691 #if BUILDFLAG(IS_TIZEN_TV)
692 thiz->ConvertUpToReturnBackIfNeeded(key_up, false);
695 // For TV IME "Select" and "Cancel" key
696 if (thiz->im_context_efl_ && thiz->im_context_efl_->IsVisible()) {
697 if (!strcmp(key_up->key, "Select") || !strcmp(key_up->key, "Cancel"))
698 thiz->im_context_efl_->HidePanel();
701 #if BUILDFLAG(IS_TIZEN_TV)
702 // In non webapp scene,"Cancel" key haven't added on the map,the keycode is
703 // 0. "Cancel" key is delivered by IME, for hiding IME panel,no need deliver
704 // the key event. Or else,the keycode 0 may exception handling by website.
705 if (!strcmp(key_up->key, "Cancel") && !blink::IsTIZENWRT())
710 KeyEvent event = MakeWebKeyEvent(false, key_up);
711 #if BUILDFLAG(IS_TIZEN_TV)
712 // Needed for HBBTV single window, multiwebview scenario.
713 event.SetDispatcher(thiz->window());
715 auto im_context_efl = thiz->GetIMContextEfl();
716 if (!im_context_efl || im_context_efl->ShouldHandleImmediately(key_up->key)) {
717 EflPlatformEventSource::GetInstance()->DispatchEflEvent(&event);
721 LOG(INFO) << "OnKeyUp,PushToKeyUpEventQueue,key:" << key_up->key;
722 im_context_efl->PushToKeyUpEventQueue(event.key_code());
725 bool EflEventHandler::IsIMEHandleKeyEventEnabled() {
726 if (!GetIMContextEfl())
729 #if BUILDFLAG(IS_TIZEN_TV)
730 return GetIMContextEfl()->ImeHandleKeyEventEnabled();
735 bool EflEventHandler::FilterIMEKeyDownEvent(Evas_Event_Key_Down* key_down) {
736 if (!IsIMEHandleKeyEventEnabled())
739 bool was_filtered = false;
740 im_context_efl_->HandleKeyDownEvent(key_down, &was_filtered);
742 // It is for checking whether key is filtered or not about keyUp event.
743 // Because the process related with key is processed at
744 // EVAS_CALLBACK_KEY_DOWN although key is processed by Ecore_IMF, it isn't
745 // filtered by ecore_imf_context_filter_event about EVAS_CALLBACK_KEY_UP.
746 was_keydown_filtered_by_platform_ = was_filtered;
748 if (IsTvProfile() && !strcmp(key_down->key, "Return"))
749 was_return_keydown_filtered_by_platform_ = was_filtered;
751 LOG(INFO) << "OnKeyDown,IME filtered the key:" << key_down->key;
756 bool EflEventHandler::FilterIMEKeyUpEvent(Evas_Event_Key_Up* key_up) {
757 if (!IsIMEHandleKeyEventEnabled())
760 // IME will change language mode when receive "Alt" keyup event.
761 // For avoiding IME change language when "Alt + Enter" scene,
762 // don't send the "Alt" keyup event when "Alt + Enter" keydown.
764 (!strcmp(key_up->key, "Alt_L") || !strcmp(key_up->key, "Alt_R")) &&
765 was_alt_enter_key_down_) {
766 was_alt_enter_key_down_ = false;
768 bool was_filtered = false;
769 im_context_efl_->HandleKeyUpEvent(key_up, &was_filtered);
772 // Both selected key and retrun key events are emitted together
773 // while typing a single key on OSK by using remote controller.
774 // The redundant retrun key event needs to be ignored here.
775 if (IsTvProfile() && evas_device_name_get(key_up->dev)) {
776 if (!strstr(evas_device_name_get(key_up->dev), "ime") &&
777 im_context_efl_->IsVisible() && !strcmp(key_up->key, "Return")) {
782 // When IME was focused out in keydown event handler,
783 // 'was_filtered' will not give the right value.
784 // Refer to 'was_return_keydown_filtered_by_platform_' in this case.
785 if (IsTvProfile() && !strcmp(key_up->key, "Return") &&
786 was_return_keydown_filtered_by_platform_) {
787 was_return_keydown_filtered_by_platform_ = false;
791 if (was_keydown_filtered_by_platform_) {
792 was_keydown_filtered_by_platform_ = false;
799 void EflEventHandler::ConvertOriginToTarget(const EflWindow* new_target,
800 LocatedEvent* event) const {
801 gfx::Vector2d diff = window_->GetBoundsInDIP().origin() -
802 new_target->GetBoundsInDIP().origin();
803 event->set_location_f(event->location_f() + diff);
806 // New requirement from tizen 6.5:
807 // press "up" key on the top of IME panel should handled as same behavior as
808 // press "Return Back" key on IME panel behavior:
809 // For WebBrowser, need hide IME panel and don't deliver the Return Back key
810 // event to WebBrowser; For WebApp, need hide IME panel and deliver the Return
811 // Back key event to WebApp.
812 #if BUILDFLAG(IS_TIZEN_TV)
813 template <typename EVT>
814 void EflEventHandler::ConvertUpToReturnBackIfNeeded(EVT* evt, bool is_press) {
815 if (!im_context_efl_ || !im_context_efl_->IsVisible() ||
816 strcmp(evt->key, "Up"))
819 // No need hide IME panel when press the IME panel's up key.
820 Evas_Device_Class device_id = evas_device_class_get(evt->dev);
821 const char* device_name = evas_device_name_get(evt->dev);
822 if (device_id != EVAS_DEVICE_CLASS_KEYBOARD || !strcmp(device_name, "ime"))
826 was_up_keypress_on_ime_top_ = true;
828 // make sure "press up key on the top of IME" scenes
829 if (!was_up_keypress_on_ime_top_)
832 was_up_keypress_on_ime_top_ = false;
835 if (blink::IsWebBrowser() || blink::IsTIZENWRT()) {
836 evt->keyname = (char*)"Cancel"; /*Return Back key name*/
837 evt->key = (char*)"Cancel"; /*Return Back key*/
838 evt->string = (char*)""; /*Return Back string*/
839 evt->keycode = 0; /*Return Back keycode*/
840 LOG(INFO) << "Press Up key on the top of IME panel, handle the Up key as "
841 "same as Return Back key!";
845 void EflEventHandler::SetKeyEventChecker(
846 const base::RepeatingCallback<bool(void*, bool)>& checker) {
847 key_event_checker_ = checker;
851 void EflEventHandler::OnMultiTouchDownEvent(void* data,
855 EflEventHandler* thiz = static_cast<EflEventHandler*>(data);
856 thiz->ProcessTouchEvents(
857 static_cast<Evas_Event_Multi_Down*>(event_info)->timestamp, true);
860 void EflEventHandler::OnMultiTouchMoveEvent(void* data,
864 EflEventHandler* thiz = static_cast<EflEventHandler*>(data);
865 thiz->ProcessTouchEvents(
866 static_cast<Evas_Event_Multi_Move*>(event_info)->timestamp, true);
869 void EflEventHandler::OnMultiTouchUpEvent(void* data,
873 EflEventHandler* thiz = static_cast<EflEventHandler*>(data);
874 thiz->ProcessTouchEvents(
875 static_cast<Evas_Event_Multi_Up*>(event_info)->timestamp, true);
878 void EflEventHandler::ProcessTouchEvents(unsigned int timestamp,
879 bool is_multi_touch) {
880 unsigned count = evas_touch_point_list_count(window_->evas());
886 Evas_Touch_Point_State state;
887 for (unsigned i = 0; i < count; ++i) {
888 id = evas_touch_point_list_nth_id_get(window_->evas(), i);
889 if ((id == 0 && is_multi_touch) || (id == 1 && !is_multi_touch))
891 evas_touch_point_list_nth_xy_get(window_->evas(), i, &pt.x, &pt.y);
892 state = evas_touch_point_list_nth_state_get(window_->evas(), i);
893 if (state == EVAS_TOUCH_POINT_STILL)
896 TouchEvent touch_event =
897 MakeTouchEvent(pt, state, id, timestamp, GetTopControlsHeight());
898 EflPlatformEventSource::GetInstance()->DispatchEflEvent(&touch_event);