55#include " tizen_window_ecore_wl2.h"
66
77#ifdef TV_PROFILE
8+ #include < app.h>
9+ #include < app_preference.h>
810#include < dlfcn.h>
11+ #include < time.h>
912#include < vconf.h>
13+ #include < sstream>
1014#endif
1115
1216#include " flutter/shell/platform/embedder/embedder.h"
@@ -23,6 +27,8 @@ constexpr int kScrollDirectionHorizontal = 1;
2327#ifdef TV_PROFILE
2428constexpr char kSysMouseCursorPointerSizeVConfKey [] =
2529 " db/menu/system/mouse-pointer-size" ;
30+ constexpr char kSysPointingDeviceSupportToastSharedPreferenceKey [] =
31+ " flutter-tizen/preference/pointing-device-support-toast" ;
2632constexpr char kEcoreWL2InputCursorThemeName [] = " vd-cursors" ;
2733#endif
2834
@@ -47,14 +53,109 @@ FlutterPointerDeviceKind ToFlutterDeviceKind(const Ecore_Device* dev) {
4753 }
4854}
4955
56+ #ifdef TV_PROFILE
57+ time_t GetBootTimeEpoch () {
58+ struct timespec now, boot_time;
59+ if (clock_gettime (CLOCK_REALTIME, &now) != 0 ) {
60+ FT_LOG (Error) << " Fail to get clock_gettime(CLOCK_REALTIME)." ;
61+ return -1 ;
62+ }
63+ if (clock_gettime (CLOCK_BOOTTIME, &boot_time) != 0 ) {
64+ FT_LOG (Error) << " Fail to get clock_gettime(CLOCK_BOOTTIME)." ;
65+ return -1 ;
66+ }
67+ time_t boot_time_epoch = now.tv_sec - boot_time.tv_sec ;
68+ return (boot_time_epoch / 10 ) * 10 ;
69+ }
70+
71+ bool PreferenceItemCallback (const char * key, void * user_data) {
72+ char * app_id = (char *)user_data;
73+ if (!app_id || !key) {
74+ return true ;
75+ }
76+
77+ std::string preference_key =
78+ std::string (kSysPointingDeviceSupportToastSharedPreferenceKey ) + " /" +
79+ app_id;
80+ if (!strncmp (key, preference_key.c_str (), preference_key.length ())) {
81+ preference_remove (key);
82+ }
83+ return true ;
84+ }
85+
86+ std::string GetPreferenceKey (bool clear_exist_key) {
87+ time_t boot_time = GetBootTimeEpoch ();
88+ if (boot_time == -1 ) {
89+ return " " ;
90+ }
91+
92+ char * id = nullptr ;
93+ int ret = app_get_id (&id);
94+ if (ret != APP_CONTROL_ERROR_NONE || !id) {
95+ FT_LOG (Error) << " Fail to get app id." ;
96+ return std::string ();
97+ }
98+
99+ std::string app_id = id;
100+ free (id);
101+
102+ std::ostringstream boot_time_buffer;
103+ boot_time_buffer << boot_time;
104+
105+ std::string preference_key =
106+ std::string (kSysPointingDeviceSupportToastSharedPreferenceKey ) + " /" +
107+ app_id + " /" + boot_time_buffer.str ();
108+
109+ if (clear_exist_key) {
110+ preference_foreach_item (PreferenceItemCallback, (void *)app_id.c_str ());
111+ }
112+ return preference_key;
113+ }
114+
115+ bool GetPointingDeviceToastPreference () {
116+ bool show_unsupported_toast = false ;
117+ std::string preference_key = GetPreferenceKey (false );
118+ if (preference_key.empty ()) {
119+ return false ;
120+ }
121+
122+ int ret =
123+ preference_get_boolean (preference_key.c_str (), &show_unsupported_toast);
124+ if (ret != PREFERENCE_ERROR_NONE) {
125+ return false ;
126+ }
127+ return show_unsupported_toast;
128+ }
129+
130+ void SetPointingDevicePreference () {
131+ std::string preference_key = GetPreferenceKey (true );
132+ if (preference_key.empty ()) {
133+ return ;
134+ }
135+
136+ int ret = preference_set_boolean (preference_key.c_str (), true );
137+ if (ret != PREFERENCE_ERROR_NONE) {
138+ FT_LOG (Error) << " Fail to set toasted preference." ;
139+ }
140+ }
141+ #endif
142+
50143} // namespace
51144
52145TizenWindowEcoreWl2::TizenWindowEcoreWl2 (TizenGeometry geometry,
53146 bool transparent,
54147 bool focusable,
55148 bool top_level,
149+ bool pointing_device_support,
150+ bool floating_menu_support,
56151 void * window_handle = nullptr )
57- : TizenWindow(geometry, transparent, focusable, top_level) {
152+ : TizenWindow(geometry, transparent, focusable, top_level)
153+ #ifdef TV_PROFILE
154+ ,
155+ pointing_device_support_ (pointing_device_support),
156+ floating_menu_support_(floating_menu_support)
157+ #endif
158+ {
58159 if (!CreateWindow (window_handle)) {
59160 FT_LOG (Error) << " Failed to create a platform window." ;
60161 return ;
@@ -64,7 +165,7 @@ TizenWindowEcoreWl2::TizenWindowEcoreWl2(TizenGeometry geometry,
64165 RegisterEventHandlers ();
65166 PrepareInputMethod ();
66167 Show ();
67- }
168+ } // namespace flutter
68169
69170TizenWindowEcoreWl2::~TizenWindowEcoreWl2 () {
70171 UnregisterEventHandlers ();
@@ -155,7 +256,6 @@ void TizenWindowEcoreWl2::SetWindowOptions() {
155256#endif
156257 ecore_wl2_window_available_rotations_set (ecore_wl2_window_, rotations,
157258 sizeof (rotations) / sizeof (int ));
158-
159259 EnableCursor ();
160260}
161261
@@ -223,6 +323,84 @@ void TizenWindowEcoreWl2::EnableCursor() {
223323#endif
224324}
225325
326+ #ifdef TV_PROFILE
327+ typedef enum _MouseSupport { DISABLE = 0 , ENABLE } MouseSupport;
328+ typedef enum _Device_Type { MOUSE_DEVICE = 3 , TOUCH_DEVICE } Device_Type;
329+
330+ void TizenWindowEcoreWl2::SetPointingDeviceSupport () {
331+ // dlopen is used here because the TV-specific library libvd-win-util.so
332+ // and the relevant headers are not present in the rootstrap.
333+ void * handle = dlopen (" libvd-win-util.so" , RTLD_LAZY);
334+ if (!handle) {
335+ FT_LOG (Error) << " Could not open a shared library libvd-win-util.so." ;
336+ return ;
337+ }
338+
339+ // These functions are defined in vd-win-util's cursor_module.h.
340+ int (*Mouse_Pointer_Support)(MouseSupport type, void * ecore_wl2_win);
341+ *(void **)(&Mouse_Pointer_Support) = dlsym (handle, " Mouse_Pointer_Support" );
342+
343+ if (!Mouse_Pointer_Support) {
344+ FT_LOG (Error) << " Could not load symbols from the library." ;
345+ dlclose (handle);
346+ return ;
347+ }
348+
349+ Mouse_Pointer_Support (pointing_device_support_ ? ENABLE : DISABLE,
350+ ecore_wl2_window_);
351+ dlclose (handle);
352+ }
353+
354+ void TizenWindowEcoreWl2::SetFloatingMenuSupport () {
355+ // dlopen is used here because the TV-specific library libvd-win-util.so
356+ // and the relevant headers are not present in the rootstrap.
357+ void * handle = dlopen (" libvd-win-util.so" , RTLD_LAZY);
358+ if (!handle) {
359+ FT_LOG (Error) << " Could not open a shared library libvd-win-util.so." ;
360+ return ;
361+ }
362+
363+ // These functions are defined in vd-win-util's cursor_module.h.
364+ int (*Mouse_Pointer_Not_Allow)(int enable, void * ecore_wl2_win);
365+ *(void **)(&Mouse_Pointer_Not_Allow) =
366+ dlsym (handle, " Mouse_Pointer_Not_Allow" );
367+
368+ if (!Mouse_Pointer_Not_Allow) {
369+ FT_LOG (Error) << " Could not load symbols from the library." ;
370+ dlclose (handle);
371+ return ;
372+ }
373+
374+ Mouse_Pointer_Not_Allow (!floating_menu_support_, ecore_wl2_window_);
375+ dlclose (handle);
376+ }
377+
378+ void TizenWindowEcoreWl2::ShowUnsupportedToast () {
379+ // dlopen is used here because the TV-specific library libvd-win-util.so
380+ // and the relevant headers are not present in the rootstrap.
381+ void * handle = dlopen (" libvd-win-util.so" , RTLD_LAZY);
382+ if (!handle) {
383+ FT_LOG (Error) << " Could not open a shared library libvd-win-util.so." ;
384+ return ;
385+ }
386+
387+ // These functions are defined in vd-win-util's cursor_module.h.
388+ void (*Unsupported_Toast_Launch)(Device_Type type, int show, int enable,
389+ void * ecore_wl2_win);
390+ *(void **)(&Unsupported_Toast_Launch) =
391+ dlsym (handle, " Unsupported_Toast_Launch" );
392+
393+ if (!Unsupported_Toast_Launch) {
394+ FT_LOG (Error) << " Could not load symbols from the library." ;
395+ dlclose (handle);
396+ return ;
397+ }
398+
399+ Unsupported_Toast_Launch (MOUSE_DEVICE, 1 , 1 , ecore_wl2_window_);
400+ dlclose (handle);
401+ }
402+ #endif
403+
226404void TizenWindowEcoreWl2::RegisterEventHandlers () {
227405 ecore_event_handlers_.push_back (ecore_event_handler_add (
228406 ECORE_WL2_EVENT_WINDOW_ROTATE,
@@ -273,6 +451,27 @@ void TizenWindowEcoreWl2::RegisterEventHandlers() {
273451 ECORE_EVENT_MOUSE_BUTTON_DOWN,
274452 [](void * data, int type, void * event) -> Eina_Bool {
275453 auto * self = static_cast <TizenWindowEcoreWl2*>(data);
454+ #ifdef TV_PROFILE
455+ if ((!self->pointing_device_support_ ||
456+ !self->floating_menu_support_ ) &&
457+ !self->show_unsupported_toast_ ) {
458+ bool shown = GetPointingDeviceToastPreference ();
459+ if (!self->floating_menu_support_ ) {
460+ self->SetFloatingMenuSupport ();
461+ }
462+ if (!shown) {
463+ // Toast popup should be called first to set up D-PAD.
464+ self->ShowUnsupportedToast ();
465+ SetPointingDevicePreference ();
466+ }
467+ self->show_unsupported_toast_ = true ;
468+ if (self->floating_menu_support_ && !self->pointing_device_support_ ) {
469+ self->SetPointingDeviceSupport ();
470+ }
471+ return ECORE_CALLBACK_PASS_ON;
472+ }
473+ #endif
474+
276475 if (self->view_delegate_ ) {
277476 auto * button_event =
278477 reinterpret_cast <Ecore_Event_Mouse_Button*>(event);
@@ -440,8 +639,8 @@ bool TizenWindowEcoreWl2::SetGeometry(TizenGeometry geometry) {
440639 geometry.left , geometry.top ,
441640 geometry.width , geometry.height );
442641 // FIXME: The changes set in `ecore_wl2_window_geometry_set` seems to apply
443- // only after calling `ecore_wl2_window_position_set`. Call a more appropriate
444- // API that flushes geometry settings to the compositor.
642+ // only after calling `ecore_wl2_window_position_set`. Call a more
643+ // appropriate API that flushes geometry settings to the compositor.
445644 ecore_wl2_window_position_set (ecore_wl2_window_, geometry.left , geometry.top );
446645 return true ;
447646}
0 commit comments