2 * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "wrt/src/browser/tv/popup_tv.h"
21 #include "base/files/file_path.h"
22 #include "base/path_service.h"
23 #include "tizen_src/chromium_impl/content/common/paths_efl.h"
24 #include "wrt/src/browser/popup_string.h"
25 #include "wrt/src/browser/wrt_native_window.h"
26 #include "wrt/src/common/locale_manager.h"
32 const char* kStateFocused = "focused";
33 const char* kStyleCheck = "C_Checkbox_WhiteText";
34 const char* kStylePopup = "C_PopupBasic_WhiteBottom";
35 const char* kWRTEdjeFile = "wrtjs_tizen.edj";
37 const unsigned int kTimeout = 60; // second
39 int syspopup_pid_ = -1;
41 Evas_Object* CreateNewWindow(Evas_Object* parent) {
45 Evas_Object* window = elm_win_add(parent, "WRTPopupWindow", ELM_WIN_BASIC);
49 elm_win_title_set(window, "WRTPopupWindow");
50 elm_win_alpha_set(window, EINA_TRUE);
51 elm_win_indicator_mode_set(window, ELM_WIN_INDICATOR_HIDE);
53 if (elm_win_wm_rotation_supported_get(parent)) {
54 int rots[] = {0, 90, 180, 270};
55 elm_win_wm_rotation_available_rotations_set(window, rots, 4);
58 int window_width, window_height;
59 elm_win_screen_size_get(window, nullptr, nullptr, &window_width,
61 evas_object_resize(window, window_width, window_height);
63 elm_win_conformant_set(window, EINA_TRUE);
64 Evas_Object* conformant = elm_conformant_add(window);
65 evas_object_size_hint_weight_set(conformant, EVAS_HINT_EXPAND,
67 elm_win_resize_object_add(window, conformant);
68 evas_object_show(conformant);
73 static void EntryKeyDownCallback(void* data,
77 if (!data || !obj || !event_info) {
78 LOG(ERROR) << "parameter is nullptr";
81 Evas_Event_Key_Down* ev = static_cast<Evas_Event_Key_Down*>(event_info);
83 LOG(ERROR) << "ev->key is nullptr";
86 PopupTV* popup = static_cast<PopupTV*>(data);
87 popup->HandleEntryKeyDownEvent(ev->key);
93 std::unique_ptr<PopupTV> PopupTV::CreatePopup(Evas_Object* window) {
94 window = CreateNewWindow(window);
96 Evas_Object* popup = elm_popup_add(window);
97 evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
98 elm_object_style_set(popup, kStylePopup);
100 Evas_Object* box = elm_box_add(popup);
101 elm_box_padding_set(box, 0, 10);
102 evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
103 evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
105 Evas_Object* table = elm_table_add(popup);
107 LOG(ERROR) << "Failed to Create Table";
111 Evas_Object* rect = evas_object_rectangle_add(evas_object_evas_get(table));
112 evas_object_color_set(rect, 0, 0, 0, 0);
113 const double real_width = 800;
114 const double real_height = 300;
115 evas_object_size_hint_min_set(rect, real_width, real_height);
116 evas_object_size_hint_max_set(rect, real_width, real_height);
117 elm_table_pack(table, rect, 0, 0, 1, 1);
118 elm_table_pack(table, box, 0, 0, 1, 1);
119 elm_object_content_set(popup, table);
120 evas_object_show(box);
122 evas_object_event_callback_add(popup, EVAS_CALLBACK_RESIZE, nullptr, nullptr);
124 auto* instance = new PopupTV(popup, box, window);
125 return std::unique_ptr<PopupTV>(instance);
129 void PopupTV::ShowVoiceRecognitionToast(const std::string& app_title) {
130 bool font_except = false;
131 std::string lang = LocaleManager::GetSystemLocale();
132 lang = lang.substr(0, lang.find_first_of("-"));
134 const std::vector<std::string> except_lang = {
135 {"zh"}, {"sl"}, {"fa"}, {"kok"}, {"am"}, {"my"}, {"km"}, {"ckb"}, {"bh"},
138 if (std::find(except_lang.begin(), except_lang.end(), lang) !=
140 LOG(INFO) << "locale-font exception. no font re-setting";
144 const std::string mic_icon = popup_string::GetText(popup_string::kMicIcon);
145 const std::string button_search = popup_string::GetTextAndReplace(
146 popup_string::kPressButtonSearch, mic_icon);
147 const std::string speech_Recog = popup_string::GetTextAndReplace(
148 popup_string::kSpeechRecognition, app_title);
150 const std::string font_size_start =
151 font_except ? "" : "<font=SamsungOneUI_400 font_size=22>";
152 const std::string font_size_end = font_except ? "" : "</font>";
153 const std::string popup_text =
154 "<font=SamsungOneUI_700 font_size=32>"
160 font_size_start + "<align=center>" + speech_Recog + "</align>" +
163 // combine the notification text
164 LOG(INFO) << "toast popup text : " << popup_text;
167 auto bundle_for_popup = std::unique_ptr<bundle, decltype(bundle_free)*>(
168 bundle_create(), bundle_free);
169 if (!bundle_for_popup.get()) {
170 LOG(ERROR) << "bundle_create failed";
174 int bundle_ret = bundle_add_str(bundle_for_popup.get(), "type", "toast");
175 if (BUNDLE_ERROR_NONE != bundle_ret) {
176 LOG(ERROR) << "bundle_add_str failed: " << bundle_ret;
180 bundle_add_str(bundle_for_popup.get(), "text", popup_text.c_str());
181 if (BUNDLE_ERROR_NONE != bundle_ret) {
182 LOG(ERROR) << "bundle_add_str failed: " << bundle_ret;
185 bundle_ret = bundle_add_str(bundle_for_popup.get(), "timeout", "3");
186 if (BUNDLE_ERROR_NONE != bundle_ret) {
187 LOG(ERROR) << "bundle_add_str failed: " << bundle_ret;
192 aul_launch_app("org.tizen.alert-syspopup", bundle_for_popup.get());
193 if (syspopup_pid_ < 0)
194 LOG(ERROR) << "launch toast fail, return code is " << syspopup_pid_;
198 void PopupTV::HideVoiceRecognitionToast() {
199 LOG(INFO) << "hide toast, pid is " << syspopup_pid_;
200 if (syspopup_pid_ > 0) {
201 int kill_ret = aul_pause_app("org.tizen.alert-syspopup");
202 if (kill_ret != AUL_R_OK)
203 LOG(ERROR) << "hide toast fail, return code is " << kill_ret;
208 PopupTV::PopupTV(Evas_Object* popup, Evas_Object* box, Evas_Object* window)
209 : Popup(popup, box), window_(window) {
210 auto main_native_window = WRTNativeWindow::GetMainNativeWindow();
211 if (main_native_window)
212 main_native_window->AddObserver(this);
215 PopupTV::~PopupTV() {
216 auto main_native_window = WRTNativeWindow::GetMainNativeWindow();
217 if (main_native_window)
218 main_native_window->RemoveObserver(this);
221 evas_object_del(window_);
226 void PopupTV::ShowInternal(std::unique_ptr<Popup> popup) {
227 auto popup_tv = static_cast<PopupTV*>(popup.get());
228 if (popup_tv->window_)
229 evas_object_show(popup_tv->window_);
230 evas_object_show(popup_tv->popup_);
232 (popup_tv->timeout_timer_)
233 .Start(FROM_HERE, base::Seconds(kTimeout), popup_tv, &PopupTV::Timeout);
234 opened_popups_.push_back(std::move(popup));
237 void PopupTV::OnWindowShow() {
239 evas_object_show(window_);
240 elm_win_raise(window_);
244 void PopupTV::OnWindowHide() {
246 evas_object_hide(window_);
250 void PopupTV::SetButtonType(ButtonType type) {
251 Popup::SetButtonType(type);
254 auto focused_callback = [](void* instance, Evas_Object* button,
255 void* /*eventInfo*/) {
256 for (auto iterator = opened_popups_.begin();
257 iterator != opened_popups_.end(); ++iterator) {
258 if (iterator->get() == instance) {
259 if ((static_cast<PopupTV*>(instance)->timeout_timer_).IsRunning())
260 (static_cast<PopupTV*>(instance)->timeout_timer_).Reset();
264 LOG(ERROR) << "Fail to get Popup instance";
266 evas_object_smart_callback_add(button1_, kStateFocused, focused_callback,
268 evas_object_smart_callback_add(button2_, kStateFocused, focused_callback,
273 void PopupTV::SetCheckBox(const std::string& id) {
274 checkStyle_ = kStyleCheck;
275 Popup::SetCheckBox(id);
278 Evas_Object* PopupTV::AddEntry(const char* id, Popup::EntryType type) {
279 base::FilePath edje_dir;
280 base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edje_dir);
281 edjeFilePath_ = edje_dir.value() + "/" + kWRTEdjeFile;
283 Evas_Object* entry = Popup::AddEntry(id, type);
284 evas_object_event_callback_add(entry, EVAS_CALLBACK_KEY_DOWN,
285 EntryKeyDownCallback, this);
289 void PopupTV::HandleEntryKeyDownEvent(const std::string& key) {
290 if (key == "Cancel") {
291 elm_object_focus_set(button1_, EINA_TRUE);
292 } else if (key == "Select") {
293 elm_object_focus_set(button2_, EINA_TRUE);
297 void PopupTV::Timeout() {
298 LOG(INFO) << "popup is timeout";
299 // button1 is negative, button2 is positive
300 elm_object_signal_emit(button1_, "elm,action,click", "elm");