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.
5 #include "xwalk/runtime/browser/ui/native_app_window_tizen.h"
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"
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_));
29 void NativeAppWindowTizen::Initialize() {
30 NativeAppWindowViews::Initialize();
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();
36 aura::Window* root_window = GetNativeWindow()->GetRootWindow();
38 root_window->AddObserver(this);
40 OrientationMask ua_default =
41 XWalkBrowserMainPartsTizen::GetAllowedUAOrientations();
42 OnAllowedOrientationsChanged(ua_default);
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);
53 NativeAppWindowTizen::~NativeAppWindowTizen() {
54 if (SensorProvider::GetInstance())
55 SensorProvider::GetInstance()->RemoveObserver(this);
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());
68 void NativeAppWindowTizen::OnWindowBoundsChanged(
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);
75 // Change the bounds of child windows to make touch work correctly.
76 GetNativeWindow()->parent()->SetBounds(new_bounds);
77 GetNativeWindow()->SetBounds(new_bounds);
79 GetWidget()->GetRootView()->SetSize(new_bounds.size());
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);
88 void NativeAppWindowTizen::OnWindowVisibilityChanging(
89 aura::Window* window, bool visible) {
91 ApplyDisplayRotation();
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:
103 case gfx::Display::ROTATE_90:
104 rotate.Translate(display_.bounds().width() - one_pixel, 0);
107 case gfx::Display::ROTATE_270:
108 rotate.Translate(0, display_.bounds().height() - one_pixel);
111 case gfx::Display::ROTATE_180:
112 rotate.Translate(display_.bounds().width() - one_pixel,
113 display_.bounds().height() - one_pixel);
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)
131 bool IsLandscapeOrientation(const gfx::Display::Rotation& rotation) {
132 return rotation == gfx::Display::ROTATE_90 ||
133 rotation == gfx::Display::ROTATE_270;
138 gfx::Display::Rotation NativeAppWindowTizen::GetClosestAllowedRotation(
139 gfx::Display::Rotation rotation) const {
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);
146 // Test current orientation
147 if (allowed_orientations_ & result)
150 // Test orientation right of current one.
151 if (allowed_orientations_ & rotl4(result, 1))
152 return static_cast<gfx::Display::Rotation>((rotation + 1) % 4);
154 // Test orientation left of current one.
155 if (allowed_orientations_ & rotl4(result, 3))
156 return static_cast<gfx::Display::Rotation>((rotation + 3) % 4);
158 // Test orientation opposite of current one.
159 if (allowed_orientations_ & rotl4(result, 2))
160 return static_cast<gfx::Display::Rotation>((rotation + 2) % 4);
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;
178 return PORTRAIT_PRIMARY;
182 void NativeAppWindowTizen::OnAllowedOrientationsChanged(
183 OrientationMask orientations) {
184 allowed_orientations_ = orientations;
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();
192 rotation = GetClosestAllowedRotation(rotation);
193 if (display_.rotation() == rotation)
196 display_.set_rotation(rotation);
197 ApplyDisplayRotation();
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.
205 rotation = GetClosestAllowedRotation(rotation);
206 if (display_.rotation() == rotation)
209 display_.set_rotation(rotation);
211 ApplyDisplayRotation();
214 void NativeAppWindowTizen::UpdateTopViewOverlay() {
215 top_view_layout()->SetUseOverlay(
216 IsLandscapeOrientation(display_.rotation()));
219 void NativeAppWindowTizen::ApplyDisplayRotation() {
221 observer()->OnOrientationChanged(GetCurrentOrientation());
223 aura::Window* root_window = GetNativeWindow()->GetRootWindow();
224 if (!root_window->IsVisible())
226 UpdateTopViewOverlay();
227 indicator_widget_->SetDisplay(display_);
228 root_window->SetTransform(GetRotationTransform());