Remove dummy object which is used for focus issue.
[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 <cstdint>
21
22 #include "common/arraysize.h"
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
31 const int kPortraitNaturalAngle[] = {
32   0,  // PORTRAIT_PRIMARY
33   180,  // PORTRAIT_SECONDARY
34   270,  // LANDSCAPE_PRIMARY
35   90,  // LANDSCAPE_SECONDARY
36   0,  // NATURAL
37   -1  // ANY
38 };
39 const int kLandscapeNaturalAngle[] = {
40   270,  // PORTRAIT_PRIMARY
41   90,  // PORTRAIT_SECONDARY
42   0,  // LANDSCAPE_PRIMARY
43   180,  // LANDSCAPE_SECONDARY
44   0,  // NATURAL
45   -1,  // ANY
46 };
47
48 NativeWindow::ScreenOrientation NativeAngleToOrientation(
49     int angle, NativeWindow::ScreenOrientation natural_orientation) {
50   auto& convert_table =
51       natural_orientation == NativeWindow::ScreenOrientation::PORTRAIT_PRIMARY ?
52           kPortraitNaturalAngle :
53           kLandscapeNaturalAngle;
54   unsigned index = ARRAYSIZE(convert_table) - 1;
55   for (unsigned i = 0; i < ARRAYSIZE(convert_table); ++i) {
56     if (convert_table[i] == angle) {
57       index = i;
58       break;
59     }
60   }
61   return static_cast<NativeWindow::ScreenOrientation>(index);
62 }
63
64 }  // namespace
65
66
67 NativeWindow::NativeWindow()
68     : window_(NULL),
69       window_type_(Type::NORMAL),
70       initialized_(false),
71       layout_(NULL),
72       content_(NULL),
73       rotation_(0),
74       handler_id_(0) {
75 }
76
77 NativeWindow::~NativeWindow() {
78   if (window_)
79     evas_object_del(window_);
80 }
81
82 void NativeWindow::Initialize() {
83   if (initialized_) {
84     LOGGER(DEBUG) << "already initialized";
85     return;
86   }
87   // window
88   window_ = CreateWindowInternal();
89   elm_win_conformant_set(window_, EINA_TRUE);
90   int w, h;
91   ecore_wl_screen_size_get(&w, &h);
92   evas_object_resize(window_, w, h);
93   elm_win_size_base_set(window_, w, h);
94   elm_win_autodel_set(window_, EINA_TRUE);
95   evas_object_smart_callback_add(window_, "delete,request",
96                                  DidDeleteRequested, this);
97   evas_object_smart_callback_add(window_, "profile,changed",
98                                  DidProfileChanged, this);
99
100   #define EVAS_SIZE_EXPAND_FILL(obj) \
101     evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); \
102     evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
103
104   // background
105   Evas_Object* bg = evas_object_rectangle_add(evas_object_evas_get(window_));
106   evas_object_color_set(bg, 0, 0, 0, 255);
107   EVAS_SIZE_EXPAND_FILL(bg);
108   elm_win_resize_object_add(window_, bg);
109   evas_object_render_op_set(bg, EVAS_RENDER_BLEND);
110   evas_object_show(bg);
111
112   // conformant
113   Evas_Object* conformant = elm_conformant_add(window_);
114   EVAS_SIZE_EXPAND_FILL(conformant);
115   elm_win_resize_object_add(window_, conformant);
116   evas_object_show(conformant);
117
118   // top layout
119   Evas_Object* top_layout = elm_layout_add(conformant);
120   elm_layout_file_set(top_layout, kEdjePath, "web-application");
121   EVAS_SIZE_EXPAND_FILL(top_layout);
122   elm_object_content_set(conformant, top_layout);
123   evas_object_show(top_layout);
124   layout_ = top_layout;
125
126   // Rotation
127   auto rotation_callback = [](void* user_data,
128                               Evas_Object* obj,
129                               void*) -> void {
130       NativeWindow* window = static_cast<NativeWindow*>(user_data);
131       int degree = elm_win_rotation_get(obj);
132       window->DidRotation(degree);
133   };
134   evas_object_smart_callback_add(window_,
135                                  kWinowRotationEventKey,
136                                  rotation_callback,
137                                  this);
138
139   if (w > h) {
140     natural_orientation_ = ScreenOrientation::LANDSCAPE_PRIMARY;
141   } else {
142     natural_orientation_ = ScreenOrientation::PORTRAIT_PRIMARY;
143   }
144
145   initialized_ = true;
146 }
147
148 void NativeWindow::DidDeleteRequested(void* /*data*/,
149     Evas_Object* /*obj*/, void* /*event_info*/) {
150   LOGGER(DEBUG) << "didDeleteRequested";
151   elm_exit();
152 }
153
154 void NativeWindow::DidProfileChanged(void* /*data*/,
155     Evas_Object* /*obj*/, void* /*event_info*/) {
156   LOGGER(DEBUG) << "didProfileChanged";
157 }
158
159 Evas_Object* NativeWindow::evas_object() const {
160   return window_;
161 }
162
163 void NativeWindow::SetContent(Evas_Object* content) {
164   // Remarks
165   // If any object was already set as a content object in the same part,
166   // the previous object will be deleted automatically with this call.
167   // If the content is NULL, this call will just delete the previous object.
168   // If the If you wish to preserve it,
169   // issue elm_object_part_content_unset() on it first.
170
171   evas_object_show(content);
172
173   // Hide unseted evas object to avoid focus and event callback problem.
174   evas_object_hide(
175     elm_object_part_content_unset(layout_, "elm.swallow.content"));
176   elm_object_part_content_set(layout_, "elm.swallow.content", content);
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 int NativeWindow::AddRotationHandler(RotationHandler handler) {
192   int id = handler_id_++;
193   handler_table_[id] = handler;
194   return id;
195 }
196
197 void NativeWindow::RemoveRotationHandler(int id) {
198   handler_table_.erase(id);
199 }
200
201 NativeWindow::ScreenOrientation NativeWindow::orientation() const {
202   return NativeAngleToOrientation(rotation_, natural_orientation_);
203 }
204
205 void NativeWindow::SetRotationLock(int degree) {
206   if (degree != -1)
207     rotation_ = degree % 360;
208   elm_win_wm_rotation_preferred_rotation_set(window_, rotation_);
209 }
210
211 void NativeWindow::SetRotationLock(ScreenOrientation orientation) {
212   auto& convert_table =
213       natural_orientation_ == ScreenOrientation::PORTRAIT_PRIMARY ?
214           kPortraitNaturalAngle :
215           kLandscapeNaturalAngle;
216   SetRotationLock(convert_table[static_cast<int>(orientation)]);
217 }
218
219
220 void NativeWindow::SetAutoRotation() {
221   elm_win_wm_rotation_preferred_rotation_set(window_, -1);
222   if (elm_win_wm_rotation_supported_get(window_)) {
223     const int rotation[4] = {0, 90, 180, 270};
224     elm_win_wm_rotation_available_rotations_set(window_, rotation, 4);
225   }
226   rotation_ = elm_win_rotation_get(window_);
227 }
228
229 void NativeWindow::Show() {
230   evas_object_show(window_);
231 }
232
233 void NativeWindow::Active() {
234   elm_win_activate(window_);
235 }
236
237 void NativeWindow::InActive() {
238   elm_win_lower(window_);
239 }
240
241 void NativeWindow::FullScreen(bool enable) {
242   elm_win_indicator_opacity_set(window_,
243       enable ? ELM_WIN_INDICATOR_TRANSPARENT : ELM_WIN_INDICATOR_OPAQUE);
244 }
245
246 #ifdef MANUAL_ROTATE_FEATURE_SUPPORT
247 void NativeWindow::EnableManualRotation(bool enable) {
248   LOGGER(DEBUG) << "set manual rotation : " << (enable ? "enabled" : "disabled");
249   elm_win_wm_rotation_manual_rotation_done_set(window_, enable ? EINA_TRUE : EINA_FALSE);
250 }
251
252 void NativeWindow::ManualRotationDone() {
253   if (EINA_TRUE == elm_win_wm_rotation_manual_rotation_done_get(window_)) {
254     elm_win_wm_rotation_manual_rotation_done(window_);
255   }
256 }
257 #endif  // MANUAL_ROTATE_FEATURE_SUPPORT
258
259 }  // namespace runtime