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/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 #if defined(OS_TIZEN_MOBILE)
24 indicator_widget_(new TizenSystemIndicatorWidget()),
25 indicator_container_(new WidgetContainerView(indicator_widget_)),
27 allowed_orientations_(ANY) {
30 void NativeAppWindowTizen::Initialize() {
31 NativeAppWindowViews::Initialize();
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();
37 aura::Window* root_window = GetNativeWindow()->GetRootWindow();
39 root_window->AddObserver(this);
41 OrientationMask ua_default =
42 XWalkBrowserMainPartsTizen::GetAllowedUAOrientations();
43 OnAllowedOrientationsChanged(ua_default);
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);
54 NativeAppWindowTizen::~NativeAppWindowTizen() {
55 if (SensorProvider::GetInstance())
56 SensorProvider::GetInstance()->RemoveObserver(this);
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());
71 void NativeAppWindowTizen::OnWindowBoundsChanged(
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);
78 // Change the bounds of child windows to make touch work correctly.
79 GetNativeWindow()->parent()->SetBounds(new_bounds);
80 GetNativeWindow()->SetBounds(new_bounds);
82 GetWidget()->GetRootView()->SetSize(new_bounds.size());
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);
91 void NativeAppWindowTizen::OnWindowVisibilityChanging(
92 aura::Window* window, bool visible) {
94 ApplyDisplayRotation();
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:
106 case gfx::Display::ROTATE_90:
107 rotate.Translate(display_.bounds().width() - one_pixel, 0);
110 case gfx::Display::ROTATE_270:
111 rotate.Translate(0, display_.bounds().height() - one_pixel);
114 case gfx::Display::ROTATE_180:
115 rotate.Translate(display_.bounds().width() - one_pixel,
116 display_.bounds().height() - one_pixel);
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)
134 bool IsLandscapeOrientation(const gfx::Display::Rotation& rotation) {
135 return rotation == gfx::Display::ROTATE_90 ||
136 rotation == gfx::Display::ROTATE_270;
141 gfx::Display::Rotation NativeAppWindowTizen::GetClosestAllowedRotation(
142 gfx::Display::Rotation rotation) const {
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);
149 // Test current orientation
150 if (allowed_orientations_ & result)
153 // Test orientation right of current one.
154 if (allowed_orientations_ & rotl4(result, 1))
155 return static_cast<gfx::Display::Rotation>((rotation + 1) % 4);
157 // Test orientation left of current one.
158 if (allowed_orientations_ & rotl4(result, 3))
159 return static_cast<gfx::Display::Rotation>((rotation + 3) % 4);
161 // Test orientation opposite of current one.
162 if (allowed_orientations_ & rotl4(result, 2))
163 return static_cast<gfx::Display::Rotation>((rotation + 2) % 4);
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;
181 return PORTRAIT_PRIMARY;
185 void NativeAppWindowTizen::OnAllowedOrientationsChanged(
186 OrientationMask orientations) {
187 allowed_orientations_ = orientations;
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();
195 rotation = GetClosestAllowedRotation(rotation);
196 if (display_.rotation() == rotation)
199 display_.set_rotation(rotation);
200 ApplyDisplayRotation();
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.
208 rotation = GetClosestAllowedRotation(rotation);
209 if (display_.rotation() == rotation)
212 display_.set_rotation(rotation);
214 ApplyDisplayRotation();
217 void NativeAppWindowTizen::UpdateTopViewOverlay() {
218 top_view_layout()->SetUseOverlay(
219 IsLandscapeOrientation(display_.rotation()));
222 void NativeAppWindowTizen::ApplyDisplayRotation() {
224 observer()->OnOrientationChanged(GetCurrentOrientation());
226 aura::Window* root_window = GetNativeWindow()->GetRootWindow();
227 if (!root_window->IsVisible())
229 UpdateTopViewOverlay();
231 #if defined(OS_TIZEN_MOBILE)
232 indicator_widget_->SetDisplay(display_);
234 root_window->SetTransform(GetRotationTransform());