0d5fbd9feafea845e913026439659121a4a78dcc
[platform/framework/web/wrt.git] / src / wrt-client / window_data.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 /**
17  * @file        window_data.cpp
18  * @author      Jaroslaw Osmanski (j.osmanski@samsung.com)
19  * @version     1.0
20  * @brief       Window data class implementation
21  */
22 #include "window_data.h"
23
24 #include <ui-gadget.h>
25 #include <dpl/log/log.h>
26 #include <dpl/foreach.h>
27
28 #include <efl_assist_screen_reader.h>
29
30 namespace {
31 const char* const DELETE_REQUEST = "delete,request";
32 const char* const PROFILE_CHANGED = "profile,changed";
33 const char* const DESKTOP_ICON_PATH =
34     "/opt/share/icons/default/small/tizenScmgz.png";
35 const std::string DESKTOP_PROFILE("desktop");
36 const int PROGRESS_H = 10;
37 } // anonymous namespace
38
39 WindowData::WindowData(unsigned long pid, bool manualInit) :
40     m_win(NULL),
41     m_conformant(NULL),
42     m_topLayout(NULL),
43     m_naviframe(NULL),
44     m_mainLayout(NULL),
45     m_progressbar(NULL),
46     m_ctxpopup(NULL),
47     m_initialized(false),
48     m_currentViewModeFullScreen(false)
49 {
50     m_win = createWindow(pid);
51
52     if (!manualInit) {
53         init();
54     }
55 }
56
57 WindowData::~WindowData()
58 {
59     LogDebug("");
60     evas_object_del(m_win);
61 }
62
63 void WindowData::init()
64 {
65     Assert(m_win != NULL && "m_win is null");
66
67     if (m_initialized == true) {
68         LogDebug("Already initilized");
69         return;
70     }
71
72     m_conformant = createConformant(m_win);
73     evas_object_show(m_conformant);
74     m_topLayout = createTopLayout(m_conformant);
75     evas_object_show(m_topLayout);
76     m_naviframe = createNaviframe(m_topLayout);
77     evas_object_show(m_naviframe);
78     m_mainLayout = createMainLayout(m_naviframe);
79     evas_object_show(m_mainLayout);
80     m_focus = createFocus(m_mainLayout);
81     evas_object_show(m_focus);
82     m_progressbar = createProgressBar(m_win, m_mainLayout);
83     evas_object_show(m_progressbar);
84
85     UG_INIT_EFL(m_win, UG_OPT_INDICATOR_ENABLE);
86     m_initialized = true;
87 }
88
89 bool WindowData::initScreenReaderSupport(bool isSupportAccessibility)
90 {
91     LogDebug("called");
92     Assert(m_win != NULL && "x window is Null");
93     return ea_screen_reader_support_set(
94                m_win,
95                isSupportAccessibility ? EINA_TRUE : EINA_FALSE);
96 }
97
98 Evas_Object* WindowData::getEvasObject(Layer layer)
99 {
100     EvasObjectDataIt it = m_evasObjectData.find(layer);
101     if (it == m_evasObjectData.end()) {
102         return NULL;
103     }
104     return it->second;
105 }
106
107 void WindowData::setWebview(Evas_Object* webview)
108 {
109     elm_object_part_content_set(m_focus, "elm.swallow.content", webview);
110     elm_object_focus_set(m_focus, EINA_TRUE);
111 }
112
113 void WindowData::unsetWebview()
114 {
115     elm_object_part_content_unset(m_focus, "elm.swallow.content");
116 }
117
118 void WindowData::smartCallbackAdd(
119     Layer layer,
120     const char* event,
121     Evas_Smart_Cb callback,
122     const void* data)
123 {
124     Evas_Object* obj = getEvasObject(layer);
125     if (!obj) {
126         LogError("Fail to get Evas_Object");
127         return;
128     }
129     evas_object_smart_callback_add(obj, event, callback, data);
130     return;
131 }
132
133 void WindowData::smartCallbackDel(
134     Layer layer,
135     const char* event,
136     Evas_Smart_Cb callback)
137 {
138     Evas_Object* obj = getEvasObject(layer);
139     if (!obj) {
140         LogError("Fail to get Evas_Object");
141         return;
142     }
143     evas_object_smart_callback_del(m_focus, event, callback);
144 }
145
146 void WindowData::signalEmit(Layer layer,
147                             const char* emission,
148                             const char* source)
149 {
150     Evas_Object* obj = getEvasObject(layer);
151     if (!obj) {
152         LogError("Fail to get Evas_Object");
153         return;
154     }
155     edje_object_signal_emit(elm_layout_edje_get(obj), emission, source);
156 }
157
158 void WindowData::setViewMode(bool fullscreen, bool backbutton)
159 {
160     LogDebug("fullscreen: " << fullscreen);
161     LogDebug("backbutton: " << backbutton);
162
163     m_currentViewModeFullScreen = fullscreen;
164     toggleIndicator(fullscreen);
165 }
166
167 void WindowData::setOrientation(int angle)
168 {
169     LogDebug("setOrientation");
170     Assert(m_win);
171     elm_win_wm_rotation_preferred_rotation_set(m_win, angle);
172 }
173
174 void WindowData::toggleFullscreen(bool fullscreen)
175 {
176     toggleIndicator(fullscreen || m_currentViewModeFullScreen);
177 }
178
179 void WindowData::showCtxpopup(void)
180 {
181     m_ctxpopup = createCtxPopup(m_naviframe);
182     if (!m_ctxpopup) {
183         return;
184     }
185     evas_object_show(m_ctxpopup);
186 }
187
188 void WindowData::setCtxpopupItemData(CtxpopupItemDataList data)
189 {
190     m_ctxpopupItemDataList = data;
191 }
192
193 void WindowData::updateProgress(double value)
194 {
195     int x, y, w, h;
196     evas_object_geometry_get(m_mainLayout, &x, &y, &w, &h);
197     evas_object_resize(m_progressbar,
198                        static_cast<int>(w * value),
199                        static_cast<int>(PROGRESS_H * elm_config_scale_get()));
200 }
201
202 void WindowData::setEvasObjectData(Layer layer, Evas_Object* obj)
203 {
204     m_evasObjectData[layer] = obj;
205 }
206
207 Evas_Object* WindowData::createWindow(unsigned long pid)
208 {
209     elm_config_preferred_engine_set("opengl_x11");
210     ADD_PROFILING_POINT("elm_win_add", "start");
211     Evas_Object* window = elm_win_add(NULL, "wrt-widget", ELM_WIN_BASIC);
212     ADD_PROFILING_POINT("elm_win_add", "stop");
213     ecore_x_window_prop_property_set(
214         elm_win_xwindow_get(window),
215         ECORE_X_ATOM_NET_WM_PID,
216         ECORE_X_ATOM_CARDINAL, 32, &pid, 1);
217     elm_win_conformant_set(window, EINA_TRUE);
218     int w, h;
219     ecore_x_window_size_get(ecore_x_window_root_first_get(), &w, &h);
220     evas_object_resize(window, w, h);
221     elm_win_autodel_set(window, EINA_TRUE);
222     evas_object_smart_callback_add(window,
223                                    DELETE_REQUEST,
224                                    winDeleteRequestCallback,
225                                    this);
226     evas_object_smart_callback_add(window,
227                                    PROFILE_CHANGED,
228                                    winProfileChangedCallback,
229                                    this);
230     setEvasObjectData(Layer::WINDOW, window);
231     return window;
232 }
233
234 Evas_Object* WindowData::createConformant(Evas_Object* parent)
235 {
236     Assert(parent != NULL && "Parent is null");
237     Evas_Object* obj = elm_conformant_add(parent);
238     evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
239     evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
240     elm_win_resize_object_add(parent, obj);
241     setEvasObjectData(Layer::CONFORMANT, obj);
242     return obj;
243 }
244
245 Evas_Object* WindowData::createTopLayout(Evas_Object* parent)
246 {
247     Assert(parent != NULL && "Parent is null");
248     Evas_Object* obj = elm_layout_add(parent);
249     elm_layout_theme_set(obj, "layout", "application", "default");
250     evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
251     evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
252     elm_object_content_set(parent, obj);
253     setEvasObjectData(Layer::TOP_LAYOUT, obj);
254     return obj;
255 }
256
257 Evas_Object* WindowData::createNaviframe(Evas_Object* parent)
258 {
259     Assert(parent != NULL && "Parent is null");
260     Evas_Object* obj = elm_naviframe_add(parent);
261     evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
262     evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
263     elm_object_part_content_set(parent, "elm.swallow.content", obj);
264     setEvasObjectData(Layer::NAVIFRAME, obj);
265     return obj;
266 }
267
268 Evas_Object* WindowData::createMainLayout(Evas_Object* parent)
269 {
270     Assert(parent != NULL && "Parent is null");
271     Evas_Object* obj = elm_layout_add(parent);
272     elm_layout_file_set(obj, WRT_EDJ_PATH, "web-application");
273     evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
274     evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
275     ADD_PROFILING_POINT("elm_naviframe_item_push", "start");
276     Elm_Object_Item* naviIt =
277         elm_naviframe_item_push(
278             parent, // Evas_Object* obj
279             NULL,   // const char* title_label
280             NULL,   // Evas_Object* prev_btn
281             NULL,   // Evas_Object* next_btn
282             obj,    // Evas_Object* content
283             NULL);  // const char* item_style
284     ADD_PROFILING_POINT("elm_naviframe_item_push", "stop");
285     elm_naviframe_item_title_visible_set(naviIt, EINA_FALSE);
286     setEvasObjectData(Layer::MAIN_LAYOUT, obj);
287     return obj;
288 }
289
290 Evas_Object* WindowData::createFocus(Evas_Object* parent)
291 {
292     Assert(parent != NULL && "Parent is null");
293     // ewkview isn't elementary widget style. This is reason why ewkview focus
294     // doesn't restore after focus-out and focus-in. To support focus restore
295     // for ewkview, WRT add selectable elementary(button) to manage focus
296     Evas_Object* obj = elm_button_add(parent);
297     elm_object_style_set(obj, "transparent");
298     elm_object_part_content_set(parent, "elm.swallow.content", obj);
299     evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
300     evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
301     setEvasObjectData(Layer::FOCUS, obj);
302     return obj;
303 }
304
305 Evas_Object* WindowData::createProgressBar(Evas_Object* window, Evas_Object* parent)
306 {
307     Assert(parent != NULL && "Parent is null");
308     Evas_Object* obj = evas_object_rectangle_add(evas_object_evas_get(window));
309     evas_object_color_set(obj, 91, 166, 255, 255);
310     elm_object_part_content_set(parent, "elm.swallow.progress", obj);
311     evas_object_resize(obj, 0, 0);
312     setEvasObjectData(Layer::PROGRESSBAR, obj);
313     return obj;
314 }
315
316 Evas_Object* WindowData::createCtxPopup(Evas_Object* parent)
317 {
318     Assert(parent != NULL && "Parent is null");
319     if (m_ctxpopupItemDataList.empty()) {
320         LogError("menu data is empty");
321         return NULL;
322     }
323
324     Evas_Object* object = elm_ctxpopup_add(parent);
325     FOREACH(it, m_ctxpopupItemDataList) {
326         Evas_Object* icon = NULL;
327         if (!it->iconPath.empty()) {
328             // create icon
329         }
330         elm_ctxpopup_item_append(object,
331                                  it->text.c_str(),
332                                  icon,
333                                  ctxpopupItemCallback,
334                                  this);
335     }
336
337     Elm_Object_Item* naviIt = elm_naviframe_top_item_get(parent);
338     Evas_Object* moreButton =
339         elm_object_item_part_content_get(naviIt, "toolbar_more_btn");
340     if (moreButton) {
341         Evas_Coord x, y, w, h;
342         evas_object_geometry_get(moreButton, &x, &y, &w, &h);
343         evas_object_move(object, x+w/2, y+h/2);
344     }
345     evas_object_smart_callback_add(object,
346                                    "dismissed",
347                                    ctxpopupDismissedCallback,
348                                    this);
349     return object;
350 }
351
352 void WindowData::toggleIndicator(bool fullscreen)
353 {
354     LogDebug("fullscreen=" << (fullscreen ? "true" : "false"));
355
356     if (!fullscreen) {
357         elm_win_indicator_mode_set(m_win, ELM_WIN_INDICATOR_SHOW);
358     } else {
359         elm_win_indicator_mode_set(m_win, ELM_WIN_INDICATOR_HIDE);
360     }
361 }
362
363 void WindowData::ctxpopupItemCallback(void* data,
364                                       Evas_Object* obj,
365                                       void* eventInfo)
366 {
367     LogDebug("ctxpopupItemCallback");
368     Assert(data);
369     WindowData* This = static_cast<WindowData*>(data);
370
371     Assert(eventInfo);
372     Elm_Object_Item* it = static_cast<Elm_Object_Item*>(eventInfo);
373     const char* text = elm_object_item_text_get(it);
374     LogDebug("text " << text);
375
376     FOREACH(it, This->m_ctxpopupItemDataList) {
377         if (it->text == text) {
378             it->function();
379             break;
380         }
381     }
382     Assert(obj);
383     elm_ctxpopup_dismiss(obj);
384 }
385
386 void WindowData::ctxpopupDismissedCallback(void* data,
387                                            Evas_Object* obj,
388                                            void* /*eventInfo*/)
389 {
390     LogDebug("ctxpopupDismissedCallback");
391     Assert(obj);
392     evas_object_del(obj);
393
394     Assert(data);
395     WindowData* This = static_cast<WindowData*>(data);
396     This->m_ctxpopup = NULL;
397 }
398
399 void WindowData::winDeleteRequestCallback(void* data,
400                                           Evas_Object* /*obj*/,
401                                           void* /*eventInfo*/)
402 {
403     LogDebug("call");
404     elm_exit();
405 }
406
407 void WindowData::winProfileChangedCallback(void *data,
408                                            Evas_Object* /*obj*/,
409                                            void* /*eventInfo*/)
410 {
411     LogDebug("winProfileChangedCallback");
412     if (data == NULL) {
413         return;
414     }
415     WindowData* This = static_cast<WindowData *>(data);
416     const char* profile = elm_config_profile_get();
417
418     if (DESKTOP_PROFILE == profile) {
419         elm_win_indicator_mode_set(This->m_win, ELM_WIN_INDICATOR_HIDE);
420         // set desktop icon
421         Evas_Object* icon =
422             evas_object_image_add(evas_object_evas_get(This->m_win));
423         evas_object_image_file_set(icon, DESKTOP_ICON_PATH, NULL);
424         elm_win_icon_object_set(This->m_win, icon);
425     }
426 }