Upstream version 6.34.115.0
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / browser / ui / native_app_window_tizen.cc
1 // Copyright (c) 2013 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "xwalk/runtime/browser/ui/native_app_window_tizen.h"
6
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "ui/aura/window.h"
10 #include "ui/gfx/transform.h"
11 #include "ui/gfx/rect.h"
12 #include "ui/gfx/screen.h"
13 #include "ui/views/view.h"
14 #include "ui/views/widget/widget.h"
15 #include "xwalk/runtime/browser/ui/top_view_layout_views.h"
16 #include "xwalk/runtime/browser/xwalk_browser_main_parts_tizen.h"
17
18 namespace xwalk {
19
20 NativeAppWindowTizen::NativeAppWindowTizen(
21     const NativeAppWindow::CreateParams& create_params)
22     : NativeAppWindowViews(create_params),
23 #if defined(OS_TIZEN_MOBILE)
24       indicator_widget_(new TizenSystemIndicatorWidget()),
25       indicator_container_(new WidgetContainerView(indicator_widget_)),
26 #endif
27       allowed_orientations_(ANY) {
28 }
29
30 void NativeAppWindowTizen::Initialize() {
31   NativeAppWindowViews::Initialize();
32
33   // Get display info such as device_scale_factor, and current
34   // rotation (orientation). NOTE: This is a local copy of the info.
35   display_ = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
36
37   aura::Window* root_window = GetNativeWindow()->GetRootWindow();
38   DCHECK(root_window);
39   root_window->AddObserver(this);
40
41   OrientationMask ua_default =
42       XWalkBrowserMainPartsTizen::GetAllowedUAOrientations();
43   OnAllowedOrientationsChanged(ua_default);
44
45   if (SensorProvider* sensor = SensorProvider::GetInstance()) {
46     gfx::Display::Rotation rotation
47       = GetClosestAllowedRotation(sensor->GetCurrentRotation());
48     display_.set_rotation(rotation);
49     ApplyDisplayRotation();
50     sensor->AddObserver(this);
51   }
52 }
53
54 NativeAppWindowTizen::~NativeAppWindowTizen() {
55   if (SensorProvider::GetInstance())
56     SensorProvider::GetInstance()->RemoveObserver(this);
57 }
58
59 void NativeAppWindowTizen::ViewHierarchyChanged(
60     const ViewHierarchyChangedDetails& details) {
61   if (details.is_add && details.child == this) {
62     NativeAppWindowViews::ViewHierarchyChanged(details);
63 #if defined(OS_TIZEN_MOBILE)
64     indicator_widget_->Initialize(GetNativeWindow());
65     top_view_layout()->set_top_view(indicator_container_.get());
66     AddChildView(indicator_container_.get());
67 #endif
68   }
69 }
70
71 void NativeAppWindowTizen::OnWindowBoundsChanged(
72     aura::Window* window,
73     const gfx::Rect& old_bounds,
74     const gfx::Rect& new_bounds) {
75   aura::Window* root_window = GetNativeWindow()->GetRootWindow();
76   DCHECK_EQ(root_window, window);
77
78   // Change the bounds of child windows to make touch work correctly.
79   GetNativeWindow()->parent()->SetBounds(new_bounds);
80   GetNativeWindow()->SetBounds(new_bounds);
81
82   GetWidget()->GetRootView()->SetSize(new_bounds.size());
83 }
84
85 void NativeAppWindowTizen::OnWindowDestroying(aura::Window* window) {
86   // Must be removed here and not in the destructor, as the aura::Window is
87   // already destroyed when our destructor runs.
88   window->RemoveObserver(this);
89 }
90
91 void NativeAppWindowTizen::OnWindowVisibilityChanging(
92     aura::Window* window, bool visible) {
93   if (visible)
94     ApplyDisplayRotation();
95 }
96
97 gfx::Transform NativeAppWindowTizen::GetRotationTransform() const {
98   // This method assumed a fixed portrait device. As everything
99   // is calculated from the fixed position we do not update the
100   // display bounds after rotation change.
101   gfx::Transform rotate;
102   float one_pixel = 1.0f / display_.device_scale_factor();
103   switch (display_.rotation()) {
104     case gfx::Display::ROTATE_0:
105       break;
106     case gfx::Display::ROTATE_90:
107       rotate.Translate(display_.bounds().width() - one_pixel, 0);
108       rotate.Rotate(90);
109       break;
110     case gfx::Display::ROTATE_270:
111       rotate.Translate(0, display_.bounds().height() - one_pixel);
112       rotate.Rotate(270);
113       break;
114     case gfx::Display::ROTATE_180:
115       rotate.Translate(display_.bounds().width() - one_pixel,
116                        display_.bounds().height() - one_pixel);
117       rotate.Rotate(180);
118       break;
119   }
120
121   return rotate;
122 }
123
124 namespace {
125
126 // Rotates a binary mask of 4 positions to the left.
127 unsigned rotl4(unsigned value, int shift) {
128   unsigned res = (value << shift);
129   if (res > (1 << 4) - 1)
130     res = res >> 4;
131   return res;
132 }
133
134 bool IsLandscapeOrientation(const gfx::Display::Rotation& rotation) {
135   return rotation == gfx::Display::ROTATE_90 ||
136          rotation == gfx::Display::ROTATE_270;
137 }
138
139 }  // namespace.
140
141 gfx::Display::Rotation NativeAppWindowTizen::GetClosestAllowedRotation(
142     gfx::Display::Rotation rotation) const {
143
144   unsigned result = PORTRAIT_PRIMARY;
145   // gfx::Display::Rotation starts at portrait-primary and
146   // belongs to the set [0:3].
147   result = rotl4(result, rotation);
148
149   // Test current orientation
150   if (allowed_orientations_ & result)
151     return rotation;
152
153   // Test orientation right of current one.
154   if (allowed_orientations_ & rotl4(result, 1))
155     return static_cast<gfx::Display::Rotation>((rotation + 1) % 4);
156
157   // Test orientation left of current one.
158   if (allowed_orientations_ & rotl4(result, 3))
159     return static_cast<gfx::Display::Rotation>((rotation + 3) % 4);
160
161   // Test orientation opposite of current one.
162   if (allowed_orientations_ & rotl4(result, 2))
163     return static_cast<gfx::Display::Rotation>((rotation + 2) % 4);
164
165   NOTREACHED();
166   return rotation;
167 }
168
169 Orientation NativeAppWindowTizen::GetCurrentOrientation() const {
170   switch (display_.rotation()) {
171     case gfx::Display::ROTATE_0:
172       return PORTRAIT_PRIMARY;
173     case gfx::Display::ROTATE_90:
174       return LANDSCAPE_PRIMARY;
175     case gfx::Display::ROTATE_180:
176       return PORTRAIT_SECONDARY;
177     case gfx::Display::ROTATE_270:
178       return LANDSCAPE_SECONDARY;
179     default:
180       NOTREACHED();
181       return PORTRAIT_PRIMARY;
182   }
183 }
184
185 void NativeAppWindowTizen::OnAllowedOrientationsChanged(
186     OrientationMask orientations) {
187   allowed_orientations_ = orientations;
188
189   // As we might have been locked before our current orientation
190   // might not fit with the sensor orienation.
191   gfx::Display::Rotation rotation = display_.rotation();
192   if (SensorProvider* sensor = SensorProvider::GetInstance())
193     rotation = sensor->GetCurrentRotation();
194
195   rotation = GetClosestAllowedRotation(rotation);
196   if (display_.rotation() == rotation)
197     return;
198
199   display_.set_rotation(rotation);
200   ApplyDisplayRotation();
201 }
202
203 void NativeAppWindowTizen::OnRotationChanged(
204     gfx::Display::Rotation rotation) {
205   // We always store the current sensor position, even if we do not
206   // apply it in case the window is invisible.
207
208   rotation = GetClosestAllowedRotation(rotation);
209   if (display_.rotation() == rotation)
210     return;
211
212   display_.set_rotation(rotation);
213
214   ApplyDisplayRotation();
215 }
216
217 void NativeAppWindowTizen::UpdateTopViewOverlay() {
218   top_view_layout()->SetUseOverlay(
219       IsLandscapeOrientation(display_.rotation()));
220 }
221
222 void NativeAppWindowTizen::ApplyDisplayRotation() {
223   if (observer())
224     observer()->OnOrientationChanged(GetCurrentOrientation());
225
226   aura::Window* root_window = GetNativeWindow()->GetRootWindow();
227   if (!root_window->IsVisible())
228     return;
229   UpdateTopViewOverlay();
230
231 #if defined(OS_TIZEN_MOBILE)
232   indicator_widget_->SetDisplay(display_);
233 #endif
234   root_window->SetTransform(GetRotationTransform());
235 }
236
237 }  // namespace xwalk