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