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