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