Skip to content

Commit dfe4c38

Browse files
authored
Improve key event handling for TV remote controls (#234)
* Improve key event handling for TV remote controls * Fix x64 build * Minimize key remapping * Rename kModifierMap
1 parent c8a9118 commit dfe4c38

11 files changed

+310
-220
lines changed

shell/platform/tizen/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ config("rootstrap_include_dirs") {
5353
"$local_prefix/include/ecore-wayland-1",
5454
"$local_prefix/include/ecore-wl2-1",
5555
"$local_prefix/include/efl-1",
56+
"$local_prefix/include/efl-extension",
5657
"$local_prefix/include/eina-1",
5758
"$local_prefix/include/eina-1/eina",
5859
"$local_prefix/include/emile-1",
@@ -173,6 +174,7 @@ template("embedder") {
173174
"capi-system-system-settings",
174175
"capi-ui-efl-util",
175176
"dlog",
177+
"efl-extension",
176178
"feedback",
177179
"tbm",
178180
"tdm-client",

shell/platform/tizen/channels/key_event_channel.cc

Lines changed: 227 additions & 187 deletions
Large diffs are not rendered by default.

shell/platform/tizen/channels/key_event_channel.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class KeyEventChannel {
2020
explicit KeyEventChannel(BinaryMessenger* messenger);
2121
virtual ~KeyEventChannel();
2222

23-
void SendKeyEvent(Ecore_Event_Key* key,
23+
void SendKeyEvent(Ecore_Event_Key* event,
2424
bool is_down,
2525
std::function<void(bool)> callback);
2626

shell/platform/tizen/key_event_handler.cc

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44

55
#include "key_event_handler.h"
66

7-
#ifndef __X64_SHELL__
7+
#ifdef __X64_SHELL__
8+
#include <cstdlib>
9+
#else
810
#include <app.h>
911
#endif
12+
#include <iostream>
1013

1114
#include "flutter/shell/platform/tizen/flutter_tizen_engine.h"
1215
#include "flutter/shell/platform/tizen/logger.h"
@@ -18,9 +21,28 @@ namespace {
1821
constexpr char kBackKey[] = "XF86Back";
1922
constexpr char kExitKey[] = "XF86Exit";
2023

24+
// Keys that should always be handled by the app first but not by the system.
25+
const std::vector<std::string> kBindableSystemKeys = {
26+
"XF86Menu", "XF86Back", "XF86AudioPlay",
27+
"XF86AudioPause", "XF86AudioStop", "XF86AudioNext",
28+
"XF86AudioPrev", "XF86AudioRewind", "XF86AudioForward",
29+
"XF86AudioPlayPause", "XF86AudioRecord", "XF86LowerChannel",
30+
"XF86RaiseChannel", "XF86ChannelList", "XF86PreviousChannel",
31+
"XF86SysMenu", "XF86SimpleMenu", "XF86History",
32+
"XF86Favorites", "XF86Info", "XF86Red",
33+
"XF86Green", "XF86Yellow", "XF86Blue",
34+
"XF86Subtitle", "XF86PlayBack", "XF86ChannelGuide",
35+
"XF86Caption", "XF86Exit",
36+
};
37+
2138
} // namespace
2239

2340
KeyEventHandler::KeyEventHandler(FlutterTizenEngine* engine) : engine_(engine) {
41+
if (!engine->renderer() || !engine->renderer()->IsValid()) {
42+
return;
43+
}
44+
engine->renderer()->BindKeys(kBindableSystemKeys);
45+
2446
key_event_handlers_.push_back(
2547
ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, OnKey, this));
2648
key_event_handlers_.push_back(
@@ -34,49 +56,53 @@ KeyEventHandler::~KeyEventHandler() {
3456
key_event_handlers_.clear();
3557
}
3658

37-
Eina_Bool KeyEventHandler::OnKey(void* data, int type, void* event) {
59+
Eina_Bool KeyEventHandler::OnKey(void* data, int type, void* raw_event) {
3860
auto* self = reinterpret_cast<KeyEventHandler*>(data);
39-
auto* key = reinterpret_cast<Ecore_Event_Key*>(event);
61+
auto* event = reinterpret_cast<Ecore_Event_Key*>(raw_event);
4062
auto* engine = self->engine_;
41-
auto is_down = type == ECORE_EVENT_KEY_DOWN;
63+
bool is_down = type == ECORE_EVENT_KEY_DOWN;
4264

43-
if (self->engine_->renderer()->GetWindowId() != key->window) {
65+
if (engine->renderer()->GetWindowId() != event->window) {
4466
return ECORE_CALLBACK_PASS_ON;
4567
}
4668

4769
if (is_down) {
48-
FT_LOG(Info) << "Key pressed: " << key->key << "(" << key->keycode << ")";
70+
FT_LOG(Info) << "Key symbol: " << event->key << ", code: 0x" << std::setw(8)
71+
<< std::setfill('0') << std::right << std::hex
72+
<< event->keycode;
4973
}
5074

5175
if (engine->text_input_channel()) {
52-
if (engine->text_input_channel()->SendKeyEvent(key, is_down)) {
53-
return ECORE_CALLBACK_PASS_ON;
76+
if (engine->text_input_channel()->SendKeyEvent(event, is_down)) {
77+
return ECORE_CALLBACK_DONE;
5478
}
5579
}
5680

5781
if (engine->platform_view_channel()) {
58-
engine->platform_view_channel()->SendKeyEvent(key, is_down);
82+
engine->platform_view_channel()->SendKeyEvent(event, is_down);
5983
}
6084

6185
if (engine->key_event_channel()) {
6286
engine->key_event_channel()->SendKeyEvent(
63-
key, is_down,
64-
[engine, keyname = std::string(key->keyname), is_down](bool handled) {
87+
event, is_down,
88+
[engine, symbol = std::string(event->key), is_down](bool handled) {
6589
if (handled) {
6690
return;
6791
}
68-
if (keyname == kBackKey && !is_down) {
92+
if (symbol == kBackKey && !is_down) {
6993
if (engine->navigation_channel()) {
7094
engine->navigation_channel()->PopRoute();
7195
}
72-
} else if (keyname == kExitKey && !is_down) {
73-
#ifndef __X64_SHELL__
96+
} else if (symbol == kExitKey && !is_down) {
97+
#ifdef __X64_SHELL__
98+
exit(EXIT_SUCCESS);
99+
#else
74100
ui_app_exit();
75101
#endif
76102
}
77103
});
78104
}
79-
return ECORE_CALLBACK_PASS_ON;
105+
return ECORE_CALLBACK_DONE;
80106
}
81107

82108
} // namespace flutter

shell/platform/tizen/tizen_renderer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ class TizenRenderer {
6060

6161
virtual bool IsSupportedExtension(const char* name) = 0;
6262

63+
virtual void BindKeys(const std::vector<std::string>& keys) = 0;
64+
6365
protected:
6466
explicit TizenRenderer(Geometry geometry,
6567
bool transparent,

shell/platform/tizen/tizen_renderer_ecore_wl2.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,4 +611,11 @@ void TizenRendererEcoreWl2::SetTizenPolicyNotificationLevel(int level) {
611611
tizen_policy_, ecore_wl2_window_surface_get(ecore_wl2_window_), level);
612612
}
613613

614+
void TizenRendererEcoreWl2::BindKeys(const std::vector<std::string>& keys) {
615+
for (const auto& key : keys) {
616+
ecore_wl2_window_keygrab_set(ecore_wl2_window_, key.c_str(), 0, 0, 0,
617+
ECORE_WL2_WINDOW_KEYGRAB_TOPMOST);
618+
}
619+
}
620+
614621
} // namespace flutter

shell/platform/tizen/tizen_renderer_ecore_wl2.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class TizenRendererEcoreWl2 : public TizenRenderer {
5353

5454
bool IsSupportedExtension(const char* name) override;
5555

56+
void BindKeys(const std::vector<std::string>& keys) override;
57+
5658
private:
5759
void Show();
5860

shell/platform/tizen/tizen_renderer_evas_gl.cc

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@
44

55
#include "tizen_renderer_evas_gl.h"
66

7+
#ifndef __X64_SHELL__
8+
#include <efl_extension.h>
9+
#include <ui/efl_util.h>
10+
#endif
11+
712
#include "tizen_evas_gl_helper.h"
813
Evas_GL* g_evas_gl = nullptr;
914
EVAS_GL_GLOBAL_GLES3_DEFINE();
1015

1116
#include "flutter/shell/platform/tizen/logger.h"
1217

13-
#ifndef __X64_SHELL__
14-
#include <ui/efl_util.h>
15-
#endif
16-
1718
namespace flutter {
1819

1920
TizenRendererEvasGL::TizenRendererEvasGL(Geometry geometry,
@@ -785,4 +786,12 @@ bool TizenRendererEvasGL::IsSupportedExtension(const char* name) {
785786
return strcmp(name, "EGL_TIZEN_image_native_surface") == 0;
786787
}
787788

789+
void TizenRendererEvasGL::BindKeys(const std::vector<std::string>& keys) {
790+
#ifndef __X64_SHELL__
791+
for (const auto& key : keys) {
792+
eext_win_keygrab_set(evas_window_, key.c_str());
793+
}
794+
#endif
795+
}
796+
788797
} // namespace flutter

shell/platform/tizen/tizen_renderer_evas_gl.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class TizenRendererEvasGL : public TizenRenderer {
3737

3838
void* GetWindowHandle() override { return evas_window_; }
3939

40+
Evas_Object* GetImageHandle() { return graphics_adapter_; }
41+
4042
void SetRotate(int angle) override;
4143
void SetGeometry(int32_t x,
4244
int32_t y,
@@ -51,7 +53,7 @@ class TizenRendererEvasGL : public TizenRenderer {
5153

5254
bool IsSupportedExtension(const char* name) override;
5355

54-
Evas_Object* GetImageHandle() { return graphics_adapter_; }
56+
void BindKeys(const std::vector<std::string>& keys) override;
5557

5658
private:
5759
void Show();

shell/platform/tizen/touch_event_handler.cc

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ namespace flutter {
1313

1414
TouchEventHandler::TouchEventHandler(FlutterTizenEngine* engine)
1515
: engine_(engine) {
16+
if (!engine->renderer() || !engine->renderer()->IsValid()) {
17+
return;
18+
}
1619
touch_event_handlers_.push_back(
1720
ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, OnTouch, this));
1821
touch_event_handlers_.push_back(
@@ -21,7 +24,6 @@ TouchEventHandler::TouchEventHandler(FlutterTizenEngine* engine)
2124
ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL, OnTouch, this));
2225
touch_event_handlers_.push_back(
2326
ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, OnTouch, this));
24-
window_id_ = engine_->renderer()->GetWindowId();
2527
}
2628

2729
TouchEventHandler::~TouchEventHandler() {
@@ -40,19 +42,17 @@ void TouchEventHandler::SendFlutterPointerEvent(FlutterPointerPhase phase,
4042
int device_id = 0) {
4143
// Correct errors caused by window rotation.
4244
auto geometry = engine_->renderer()->GetWindowGeometry();
43-
double width = geometry.w;
44-
double height = geometry.h;
4545
double new_x = x, new_y = y;
4646

4747
if (rotation == 90) {
48-
new_x = height - y;
48+
new_x = geometry.h - y;
4949
new_y = x;
5050
} else if (rotation == 180) {
51-
new_x = width - x;
52-
new_y = height - y;
51+
new_x = geometry.w - x;
52+
new_y = geometry.h - y;
5353
} else if (rotation == 270) {
5454
new_x = y;
55-
new_y = width - x;
55+
new_y = geometry.w - x;
5656
}
5757

5858
FlutterPointerEvent event = {};
@@ -74,10 +74,11 @@ void TouchEventHandler::SendFlutterPointerEvent(FlutterPointerPhase phase,
7474

7575
Eina_Bool TouchEventHandler::OnTouch(void* data, int type, void* event) {
7676
auto* self = reinterpret_cast<TouchEventHandler*>(data);
77+
auto window_id = self->engine_->renderer()->GetWindowId();
7778

7879
if (type == ECORE_EVENT_MOUSE_BUTTON_DOWN) {
7980
auto* button_event = reinterpret_cast<Ecore_Event_Mouse_Button*>(event);
80-
if (self->window_id_ == button_event->window) {
81+
if (window_id == button_event->window) {
8182
self->pointer_state_ = true;
8283
self->SendFlutterPointerEvent(kDown, button_event->x, button_event->y, 0,
8384
0, button_event->timestamp,
@@ -87,7 +88,7 @@ Eina_Bool TouchEventHandler::OnTouch(void* data, int type, void* event) {
8788

8889
} else if (type == ECORE_EVENT_MOUSE_BUTTON_UP) {
8990
auto* button_event = reinterpret_cast<Ecore_Event_Mouse_Button*>(event);
90-
if (self->window_id_ == button_event->window) {
91+
if (window_id == button_event->window) {
9192
self->pointer_state_ = false;
9293
self->SendFlutterPointerEvent(kUp, button_event->x, button_event->y, 0, 0,
9394
button_event->timestamp,
@@ -96,7 +97,7 @@ Eina_Bool TouchEventHandler::OnTouch(void* data, int type, void* event) {
9697
}
9798
} else if (type == ECORE_EVENT_MOUSE_MOVE) {
9899
auto* move_event = reinterpret_cast<Ecore_Event_Mouse_Move*>(event);
99-
if (self->window_id_ == move_event->window) {
100+
if (window_id == move_event->window) {
100101
if (self->pointer_state_) {
101102
self->SendFlutterPointerEvent(kMove, move_event->x, move_event->y, 0, 0,
102103
move_event->timestamp,
@@ -106,7 +107,7 @@ Eina_Bool TouchEventHandler::OnTouch(void* data, int type, void* event) {
106107
}
107108
} else if (type == ECORE_EVENT_MOUSE_WHEEL) {
108109
auto* wheel_event = reinterpret_cast<Ecore_Event_Mouse_Wheel*>(event);
109-
if (self->window_id_ == wheel_event->window) {
110+
if (window_id == wheel_event->window) {
110111
double scroll_delta_x = 0.0, scroll_delta_y = 0.0;
111112
if (wheel_event->direction == kScrollDirectionVertical) {
112113
scroll_delta_y += wheel_event->z;

0 commit comments

Comments
 (0)