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/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"
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_));
28 void NativeAppWindowTizen::Initialize() {
29 NativeAppWindowViews::Initialize();
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();
35 aura::Window* root_window = GetNativeWindow()->GetRootWindow();
37 root_window->AddObserver(this);
39 OrientationMask ua_default =
40 XWalkBrowserMainPartsTizen::GetAllowedUAOrientations();
41 OnAllowedOrientationsChanged(ua_default);
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);
52 NativeAppWindowTizen::~NativeAppWindowTizen() {
53 if (SensorProvider::GetInstance())
54 SensorProvider::GetInstance()->RemoveObserver(this);
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());
67 void NativeAppWindowTizen::OnWindowBoundsChanged(
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);
74 // Change the bounds of child windows to make touch work correctly.
75 GetNativeWindow()->parent()->SetBounds(new_bounds);
76 GetNativeWindow()->SetBounds(new_bounds);
78 GetWidget()->GetRootView()->SetSize(new_bounds.size());
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);
87 void NativeAppWindowTizen::OnWindowVisibilityChanging(
88 aura::Window* window, bool visible) {
90 ApplyDisplayRotation();
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:
102 case gfx::Display::ROTATE_90:
103 rotate.Translate(display_.bounds().width() - one_pixel, 0);
106 case gfx::Display::ROTATE_270:
107 rotate.Translate(0, display_.bounds().height() - one_pixel);
110 case gfx::Display::ROTATE_180:
111 rotate.Translate(display_.bounds().width() - one_pixel,
112 display_.bounds().height() - one_pixel);
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)
130 bool IsLandscapeOrientation(const gfx::Display::Rotation& rotation) {
131 return rotation == gfx::Display::ROTATE_90 ||
132 rotation == gfx::Display::ROTATE_270;
137 gfx::Display::Rotation NativeAppWindowTizen::GetClosestAllowedRotation(
138 gfx::Display::Rotation rotation) const {
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);
145 // Test current orientation
146 if (allowed_orientations_ & result)
149 // Test orientation right of current one.
150 if (allowed_orientations_ & rotl4(result, 1))
151 return static_cast<gfx::Display::Rotation>((rotation + 1) % 4);
153 // Test orientation left of current one.
154 if (allowed_orientations_ & rotl4(result, 3))
155 return static_cast<gfx::Display::Rotation>((rotation + 3) % 4);
157 // Test orientation opposite of current one.
158 if (allowed_orientations_ & rotl4(result, 2))
159 return static_cast<gfx::Display::Rotation>((rotation + 2) % 4);
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;
177 return PORTRAIT_PRIMARY;
181 void NativeAppWindowTizen::OnAllowedOrientationsChanged(
182 OrientationMask orientations) {
183 allowed_orientations_ = orientations;
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();
191 rotation = GetClosestAllowedRotation(rotation);
192 if (display_.rotation() == rotation)
195 display_.set_rotation(rotation);
196 ApplyDisplayRotation();
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.
204 rotation = GetClosestAllowedRotation(rotation);
205 if (display_.rotation() == rotation)
208 display_.set_rotation(rotation);
210 ApplyDisplayRotation();
213 void NativeAppWindowTizen::UpdateTopViewOverlay() {
214 top_view_layout()->SetUseOverlay(
215 IsLandscapeOrientation(display_.rotation()));
218 void NativeAppWindowTizen::ApplyDisplayRotation() {
220 observer()->OnOrientationChanged(GetCurrentOrientation());
222 aura::Window* root_window = GetNativeWindow()->GetRootWindow();
223 if (!root_window->IsVisible())
225 UpdateTopViewOverlay();
226 indicator_widget_->SetDisplay(display_);
227 root_window->SetTransform(GetRotationTransform());