Merge pull request #122 from JongHeonChoi/fx_base_window_size
[platform/framework/web/crosswalk-tizen.git] / runtime / browser / native_window.cc
1 /*
2  * Copyright (c) 2015 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 #include "runtime/browser/native_window.h"
18
19 #include <Ecore_Wayland.h>
20 #include <ewk_chromium.h>
21 #include <cstdint>
22
23 #include "common/logger.h"
24
25 namespace runtime {
26
27 namespace {
28   const char* kEdjePath = "/usr/share/edje/xwalk/xwalk_tizen.edj";
29   const char* kWinowRotationEventKey = "wm,rotation,changed";
30   const char* kWinowFocusedEventKey = "focused";
31   const char* kWinowUnfocusedEventKey = "unfocused";
32 }  // namespace
33
34
35 NativeWindow::NativeWindow()
36     : window_(NULL),
37       window_type_(Type::NORMAL),
38       initialized_(false),
39       focus_(NULL),
40       content_(NULL),
41       rotation_(0),
42       handler_id_(0) {
43 }
44
45 NativeWindow::~NativeWindow() {
46   if (window_)
47     evas_object_del(window_);
48 }
49
50 void NativeWindow::Initialize() {
51   if (initialized_) {
52     LOGGER(DEBUG) << "already initialized";
53     return;
54   }
55   // window
56   window_ = CreateWindowInternal();
57   elm_win_conformant_set(window_, EINA_TRUE);
58   int w, h;
59   ecore_wl_screen_size_get(&w, &h);
60   evas_object_resize(window_, w, h);
61   elm_win_size_base_set(window_, w, h);
62   elm_win_autodel_set(window_, EINA_TRUE);
63   evas_object_smart_callback_add(window_, "delete,request",
64                                  DidDeleteRequested, this);
65   evas_object_smart_callback_add(window_, "profile,changed",
66                                  DidProfileChanged, this);
67
68   #define EVAS_SIZE_EXPAND_FILL(obj) \
69     evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); \
70     evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
71
72   // background
73   Evas_Object* bg = evas_object_rectangle_add(evas_object_evas_get(window_));
74   evas_object_color_set(bg, 0, 0, 0, 255);
75   EVAS_SIZE_EXPAND_FILL(bg);
76   elm_win_resize_object_add(window_, bg);
77   evas_object_render_op_set(bg, EVAS_RENDER_BLEND);
78   evas_object_show(bg);
79
80   // conformant
81   Evas_Object* conformant = elm_conformant_add(window_);
82   EVAS_SIZE_EXPAND_FILL(conformant);
83   elm_win_resize_object_add(window_, conformant);
84   evas_object_show(conformant);
85
86   // top layout
87   Evas_Object* top_layout = elm_layout_add(conformant);
88   elm_layout_file_set(top_layout, kEdjePath, "web-application");
89   EVAS_SIZE_EXPAND_FILL(top_layout);
90   elm_object_content_set(conformant, top_layout);
91   evas_object_show(top_layout);
92
93   // focus
94   Evas_Object* focus = elm_bg_add(top_layout);
95   evas_object_size_hint_align_set(focus, EVAS_HINT_FILL, EVAS_HINT_FILL);
96   evas_object_size_hint_weight_set(focus, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
97   elm_object_focus_allow_set(focus, EINA_TRUE);
98   elm_object_part_content_set(top_layout, "elm.swallow.content", focus);
99   EVAS_SIZE_EXPAND_FILL(focus);
100   elm_access_object_unregister(focus);
101   evas_object_show(focus);
102   focus_ = focus;
103
104   // focus callback
105   auto focus_callback = [](void* user_data,
106                            Evas_Object*,
107                            void*) -> void {
108     NativeWindow* window = static_cast<NativeWindow*>(user_data);
109     window->DidFocusChanged(true);
110   };
111   auto unfocus_callback = [](void* user_data,
112                              Evas_Object*,
113                              void*) -> void {
114     NativeWindow* window = static_cast<NativeWindow*>(user_data);
115     window->DidFocusChanged(false);
116   };
117
118   evas_object_smart_callback_add(focus,
119                                  kWinowFocusedEventKey,
120                                  focus_callback,
121                                  this);
122   evas_object_smart_callback_add(focus,
123                                  kWinowUnfocusedEventKey,
124                                  unfocus_callback,
125                                  this);
126
127   // Rotation
128   auto rotation_callback = [](void* user_data,
129                               Evas_Object* obj,
130                               void*) -> void {
131       NativeWindow* window = static_cast<NativeWindow*>(user_data);
132       int degree = elm_win_rotation_get(obj);
133       window->DidRotation(degree);
134   };
135   evas_object_smart_callback_add(window_,
136                                  kWinowRotationEventKey,
137                                  rotation_callback,
138                                  this);
139
140   if (w > h) {
141     natural_orientation_ = ScreenOrientation::LANDSCAPE_PRIMARY;
142   } else {
143     natural_orientation_ = ScreenOrientation::PORTRAIT_PRIMARY;
144   }
145
146   initialized_ = true;
147 }
148
149 void NativeWindow::DidDeleteRequested(void* /*data*/,
150     Evas_Object* /*obj*/, void* /*event_info*/) {
151   LOGGER(DEBUG) << "didDeleteRequested";
152   elm_exit();
153 }
154
155 void NativeWindow::DidProfileChanged(void* /*data*/,
156     Evas_Object* /*obj*/, void* /*event_info*/) {
157   LOGGER(DEBUG) << "didProfileChanged";
158 }
159
160 Evas_Object* NativeWindow::evas_object() const {
161   return window_;
162 }
163
164 void NativeWindow::SetContent(Evas_Object* content) {
165   // Remarks
166   // If any object was already set as a content object in the same part,
167   // the previous object will be deleted automatically with this call.
168   // If the content is NULL, this call will just delete the previous object.
169   // If the If you wish to preserve it,
170   // issue elm_object_part_content_unset() on it first.
171
172   evas_object_show(content);
173   evas_object_hide(
174     elm_object_part_content_unset(focus_, "elm.swallow.content"));
175   elm_object_part_content_set(focus_, "elm.swallow.content", content);
176   elm_object_focus_set(focus_, EINA_TRUE);
177   content_ = content;
178
179   // attached webview was resized by evas_norender API
180   evas_norender(evas_object_evas_get(window_));
181 }
182
183 void NativeWindow::DidRotation(int degree) {
184   rotation_ = degree;
185   auto it = handler_table_.begin();
186   for ( ; it != handler_table_.end(); ++it) {
187     it->second(degree);
188   }
189 }
190
191 void NativeWindow::DidFocusChanged(bool got) {
192   if (content_ != NULL) {
193     ewk_view_focus_set(content_, got ? EINA_TRUE : EINA_FALSE);
194   }
195 }
196
197 int NativeWindow::AddRotationHandler(RotationHandler handler) {
198   int id = handler_id_++;
199   handler_table_[id] = handler;
200   return id;
201 }
202
203 void NativeWindow::RemoveRotationHandler(int id) {
204   handler_table_.erase(id);
205 }
206
207 void NativeWindow::SetRotationLock(int degree) {
208   if (degree != -1)
209     rotation_ = degree % 360;
210   elm_win_wm_rotation_preferred_rotation_set(window_, rotation_);
211 }
212
213 void NativeWindow::SetRotationLock(ScreenOrientation orientation) {
214   int portrait_natural_angle[] = {
215     0,  // PORTRAIT_PRIMARY
216     180,  // PORTRAIT_SECONDARY
217     270,  // LANDSCAPE_PRIMARY
218     90,  // LANDSCAPE_SECONDARY
219     0,  // NATURAL
220     -1  // ANY
221   };
222   int landscape_natural_angle[] = {
223     270,  // PORTRAIT_PRIMARY
224     90,  // PORTRAIT_SECONDARY
225     0,  // LANDSCAPE_PRIMARY
226     180,  // LANDSCAPE_SECONDARY
227     0,  // NATURAL
228     -1,  // ANY
229   };
230   auto& convert_table =
231       natural_orientation_ == ScreenOrientation::PORTRAIT_PRIMARY ?
232           portrait_natural_angle :
233           landscape_natural_angle;
234   SetRotationLock(convert_table[static_cast<int>(orientation)]);
235 }
236
237
238 void NativeWindow::SetAutoRotation() {
239   elm_win_wm_rotation_preferred_rotation_set(window_, -1);
240   if (elm_win_wm_rotation_supported_get(window_)) {
241     const int rotation[4] = {0, 90, 180, 270};
242     elm_win_wm_rotation_available_rotations_set(window_, rotation, 4);
243   }
244   rotation_ = elm_win_rotation_get(window_);
245 }
246
247 void NativeWindow::Show() {
248   evas_object_show(window_);
249 }
250
251 void NativeWindow::Active() {
252   elm_win_activate(window_);
253 }
254
255 void NativeWindow::InActive() {
256   elm_win_lower(window_);
257 }
258
259 void NativeWindow::FullScreen(bool enable) {
260   elm_win_indicator_opacity_set(window_,
261       enable ? ELM_WIN_INDICATOR_TRANSPARENT : ELM_WIN_INDICATOR_OPAQUE);
262 }
263
264 #ifdef MANUAL_ROTATE_FEATURE_SUPPORT
265 void NativeWindow::EnableManualRotation(bool enable) {
266   LOGGER(DEBUG) << "set manual rotation : " << (enable ? "enabled" : "disabled");
267   elm_win_wm_rotation_manual_rotation_done_set(window_, enable ? EINA_TRUE : EINA_FALSE);
268 }
269
270 void NativeWindow::ManualRotationDone() {
271   if (EINA_TRUE == elm_win_wm_rotation_manual_rotation_done_get(window_)) {
272     elm_win_wm_rotation_manual_rotation_done(window_);
273   }
274 }
275 #endif  // MANUAL_ROTATE_FEATURE_SUPPORT
276
277 }  // namespace runtime