2 * Copyright (c) 2017 - 2018 Samsung Electronics Co.
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 * @file src/agent/notification-daemon/Popupper.cpp
18 * @author Zofia Abramowska <z.abramowska@samsung.com>
19 * @author Ernest Borowski <e.borowski@partner.samsung.com>
20 * @brief Definition of Popupper class
25 #include "Answerable.h"
27 #include "PopupCheckMobile.h"
28 #include "PopupCheckWearable.h"
30 #include <exception/ErrnoException.h>
31 #include <exception/Exception.h>
36 #include <system_info.h>
42 namespace Notification {
45 std::string getProfileName() {
46 char *profileName = nullptr;
47 system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
49 ALOGE("profileName is NULL");
50 throw Exception("get profileName failed");
52 std::unique_ptr<char, decltype(free)*> profileNamePtr(profileName, free);
53 return std::string(profileName);
56 std::string getHomeKey() {
57 std::string profileName = getProfileName();
58 if (profileName[0] == 'w' || profileName[0] == 'W')
59 return "XF86PowerOff";
66 void Popupper::registerPopupResponseHandler(PopupHandler handler) {
67 m_popupResponseHandler = handler;
70 void Popupper::unfocusedCb(void *data, Evas_Object *, void *)
73 Popupper *popupper = static_cast<Popupper*>(data);
75 if (popupper->m_shouldRaise) {
76 evas_object_show(popupper->m_win);
80 void Popupper::popupClose()
82 ALOGD("Window close");
83 m_shouldRaise = false;
86 ALOGD("Closing non-existing popup");
88 m_elementPtr.reset(nullptr);
89 m_answerablePtr.reset(nullptr);
91 m_privaciesSequence.setPrivacies({});
92 evas_object_hide(m_win);
95 void Popupper::buttonAnswer(IAnswerable::Button button) {
96 NResponseType answer = m_answerablePtr->getAnswer(button);
97 m_responses.push_back(answer);
99 if (m_responses.size() == m_privaciesSequence.size()) {
100 m_popupResponseHandler(m_responses);
105 if (!m_privaciesSequence.getNextPrivacy(privacy)) {
106 ALOGE("Unable to get next privacy");
107 respondToRest(NResponseType::None);
111 if (!m_elementPtr->showNext(Po::createPopupCheckMsg(m_pkgId, privacy))) {
112 ALOGE("unable to show next popup");
113 respondToRest(NResponseType::None);
117 void Popupper::allowPressedCb(void *data, Evas_Object *, void *)
119 Popupper *popupper = static_cast<Popupper*>(data);
120 popupper->buttonAnswer(IAnswerable::Button::ALLOW);
123 void Popupper::denyPressedCb(void *data, Evas_Object *, void *)
125 Popupper *popupper = static_cast<Popupper*>(data);
126 popupper->buttonAnswer(IAnswerable::Button::DENY);
129 Eina_Bool Popupper::hwKeyClickedCb(void *data, int type, void *event)
131 Ecore_Event_Key *ev = static_cast<Ecore_Event_Key*>(event);
132 Popupper* runner = static_cast<Popupper*>(data);
134 ALOGD("HW button pressed. type <" << type << "> pressed key is <" << ev->key << ">");
135 if ((!strcmp(getHomeKey().c_str(), ev->key) || !strcmp("XF86Back", ev->key)) && runner->m_elementPtr) {
136 ALOGD("Respond as deny once.");
137 if (!strcmp("XF86Back", ev->key))
139 ecore_timer_add(delay,
140 [](void *data) -> Eina_Bool {
141 Popupper *runner = static_cast<Popupper *>(data);
142 runner->respondToRest(NResponseType::None);
143 return ECORE_CALLBACK_CANCEL;
150 Popupper::~Popupper()
153 void Popupper::initialize()
156 m_win = elm_win_add(NULL, Po::getPopupTitleMsg().c_str(), ELM_WIN_NOTIFICATION);
158 ALOGE("EFL : Failed to add window");
159 throw Exception("Elementary failed");
161 efl_util_set_notification_window_level(m_win, EFL_UTIL_NOTIFICATION_LEVEL_TOP);
163 if (elm_win_wm_rotation_supported_get(m_win)) {
164 int rots[4] = { 0, 90, 180, 270 };
165 elm_win_wm_rotation_available_rotations_set(m_win, (const int *)(&rots), 4);
168 elm_win_autodel_set(m_win, EINA_TRUE);
169 elm_win_override_set(m_win, EINA_TRUE);
170 elm_win_alpha_set(m_win, EINA_TRUE);
173 elm_win_indicator_opacity_set(m_win, ELM_WIN_INDICATOR_OPAQUE);
174 elm_win_indicator_mode_set(m_win, ELM_WIN_INDICATOR_SHOW);
175 evas_object_smart_callback_add(m_win, "unfocused", &Popupper::unfocusedCb, this);
177 elm_win_keygrab_set(m_win, getHomeKey().c_str(), 0, 0, 0, ELM_WIN_KEYGRAB_SHARED);
178 elm_win_keygrab_set(m_win, "XF86Back", 0, 0, 0, ELM_WIN_KEYGRAB_TOPMOST);
179 ecore_event_handler_add(ECORE_EVENT_KEY_UP, &Popupper::hwKeyClickedCb, this);
182 void Popupper::show() {
183 evas_object_show(m_win);
186 void Popupper::popupCheck(const std::string &pkgId, const std::vector<Privacy> &privacies) {
187 std::string profileName = getProfileName();
190 m_privaciesSequence.setPrivacies(privacies);
193 Privacy currentPrivacy;
194 if (!m_privaciesSequence.getNextPrivacy(currentPrivacy)) {
195 ALOGE("Unable to get next privacy");
196 respondToRest(NResponseType::None);
199 if (profileName[0] != 'w' && profileName[0] != 'W') {
201 popup = new PopupCheckMobile(m_win, Po::createPopupCheckMsg(pkgId, currentPrivacy), m_privaciesSequence.size());
204 popup = new PopupCheckWearable(m_win, Po::createPopupCheckMsg(pkgId, currentPrivacy),
205 pkgId, currentPrivacy, m_privaciesSequence.size());
208 } catch (const std::exception &e) {
209 ALOGE("Failed to create popup check : " << e.what());
210 respondToRest(NResponseType::None);
214 m_answerablePtr.reset(new AnswerablePopupCheck(popup));
215 evas_object_smart_callback_add(popup->getAllowButton(), "clicked", &Popupper::allowPressedCb,
217 evas_object_smart_callback_add(popup->getDenyButton(), "clicked", &Popupper::denyPressedCb,
220 m_elementPtr.reset(popup);
225 void Popupper::respondToRest(NResponseType response)
227 size_t alreadyRespondedCount = m_responses.size();
228 while (alreadyRespondedCount < m_privaciesSequence.size()) {
229 m_responses.push_back(response);
230 alreadyRespondedCount++;
232 m_popupResponseHandler(m_responses);
235 void Popupper::start()
240 void Popupper::stop()
242 m_shouldRaise = false;
243 elm_win_keygrab_unset(m_win, getHomeKey().c_str(), 0, 0);
244 elm_win_keygrab_unset(m_win, "XF86Back", 0, 0);
245 m_elementPtr.reset(nullptr);
246 m_answerablePtr.reset(nullptr);
248 evas_object_del(m_win);
253 void Popupper::shutdown() {
257 } /* namespace Notification */
259 } /* namespace AskUser */