0

Reland ScreenOrientationDelegate on ChromeOS

This change fixes the error in: https://codereview.chromium.org/648733003

This reverts commit 61aaa96a45.

TBR=avi@chromium.org, oshima@chromium.org, rbyers@chromium.org, mlamouri@chromium.org
BUG=396760

Review URL: https://codereview.chromium.org/723633003

Cr-Commit-Position: refs/heads/master@{#303952}
This commit is contained in:
jonross
2014-11-12 17:22:51 -08:00
committed by Commit bot
parent 858fd17191
commit f21fea1f36
13 changed files with 487 additions and 10 deletions

@ -47,6 +47,8 @@
'ash_touch_exploration_manager_chromeos.h',
'cancel_mode.cc',
'cancel_mode.h',
'content/display/screen_orientation_delegate_chromeos.cc',
'content/display/screen_orientation_delegate_chromeos.h',
'debug.cc',
'debug.h',
'default_accessibility_delegate.cc',
@ -771,6 +773,7 @@
'accelerators/spoken_feedback_toggler_unittest.cc',
'ash_touch_exploration_manager_chromeos_unittest.cc',
'autoclick/autoclick_unittest.cc',
'content/display/screen_orientation_delegate_chromeos_unittest.cc',
'desktop_background/desktop_background_controller_unittest.cc',
'desktop_background/wallpaper_resizer_unittest.cc',
'dip_unittest.cc',
@ -1119,6 +1122,7 @@
'conditions': [
['chromeos==0', {
'sources!': [
'content/display/screen_orientation_delegate_chromeos_unittest.cc',
# TODO(zork): fix this test to build on Windows. See: crosbug.com/26906
'focus_cycler_unittest.cc',
# All tests for multiple displays: not supported on Windows Ash.

13
ash/content/display/DEPS Normal file

@ -0,0 +1,13 @@
include_rules = [
"+content/public/browser/screen_orientation_delegate.h",
"+content/public/browser/screen_orientation_provider.h",
"+content/public/browser/browser_context.h",
"+content/public/browser/web_contents.h",
"+third_party/WebKit/public/platform/WebScreenOrientationLockType.h",
]
specific_include_rules = {
".*test\.cc": [
"+content/public/test/test_browser_context.h"
],
}

@ -0,0 +1,180 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/content/display/screen_orientation_delegate_chromeos.h"
#include "ash/ash_switches.h"
#include "ash/display/display_info.h"
#include "ash/display/display_manager.h"
#include "ash/shell.h"
#include "ash/wm/maximize_mode/maximize_mode_controller.h"
#include "base/command_line.h"
#include "content/public/browser/screen_orientation_provider.h"
#include "content/public/browser/web_contents.h"
#include "ui/aura/window.h"
#include "ui/gfx/display.h"
#include "ui/gfx/geometry/size.h"
namespace {
blink::WebScreenOrientationLockType GetDisplayNaturalOrientation() {
ash::DisplayManager* display_manager =
ash::Shell::GetInstance()->display_manager();
if (!display_manager->HasInternalDisplay())
return blink::WebScreenOrientationLockLandscape;
ash::DisplayInfo info =
display_manager->GetDisplayInfo(gfx::Display::InternalDisplayId());
gfx::Size size = info.size_in_pixel();
switch (info.rotation()) {
case gfx::Display::ROTATE_0:
case gfx::Display::ROTATE_180:
return size.height() >= size.width()
? blink::WebScreenOrientationLockPortrait
: blink::WebScreenOrientationLockLandscape;
case gfx::Display::ROTATE_90:
case gfx::Display::ROTATE_270:
return size.height() < size.width()
? blink::WebScreenOrientationLockPortrait
: blink::WebScreenOrientationLockLandscape;
}
NOTREACHED();
return blink::WebScreenOrientationLockLandscape;
}
} // namespace
namespace ash {
ScreenOrientationDelegate::ScreenOrientationDelegate()
: locking_window_(NULL),
natural_orientation_(GetDisplayNaturalOrientation()) {
content::ScreenOrientationProvider::SetDelegate(this);
}
ScreenOrientationDelegate::~ScreenOrientationDelegate() {
content::ScreenOrientationProvider::SetDelegate(NULL);
}
bool ScreenOrientationDelegate::FullScreenRequired(
content::WebContents* web_contents) {
return true;
}
void ScreenOrientationDelegate::Lock(
content::WebContents* web_contents,
blink::WebScreenOrientationLockType lock_orientation) {
aura::Window* requesting_window = web_contents->GetNativeView();
// TODO(jonross): Make ScreenOrientationDelegate responsible for rotation
// lock. Have MaximizeModeController, and TrayRotationLock both use it
// instead.
MaximizeModeController* controller =
Shell::GetInstance()->maximize_mode_controller();
// TODO(jonross): Track one rotation lock per window. When the active window
// changes apply any corresponding rotation lock.
if (!locking_window_)
locking_window_ = requesting_window;
else if (requesting_window != locking_window_)
return;
switch (lock_orientation) {
case blink::WebScreenOrientationLockAny:
controller->SetRotationLocked(false);
locking_window_ = NULL;
break;
case blink::WebScreenOrientationLockDefault:
NOTREACHED();
break;
case blink::WebScreenOrientationLockPortraitPrimary:
LockRotationToPrimaryOrientation(blink::WebScreenOrientationLockPortrait);
break;
case blink::WebScreenOrientationLockLandscape:
case blink::WebScreenOrientationLockPortrait:
LockToRotationMatchingOrientation(lock_orientation);
break;
case blink::WebScreenOrientationLockPortraitSecondary:
LockRotationToSecondaryOrientation(
blink::WebScreenOrientationLockPortrait);
break;
case blink::WebScreenOrientationLockLandscapeSecondary:
LockRotationToSecondaryOrientation(
blink::WebScreenOrientationLockLandscape);
break;
case blink::WebScreenOrientationLockLandscapePrimary:
LockRotationToPrimaryOrientation(
blink::WebScreenOrientationLockLandscape);
break;
case blink::WebScreenOrientationLockNatural:
controller->LockRotation(gfx::Display::ROTATE_0);
break;
default:
NOTREACHED();
break;
}
}
bool ScreenOrientationDelegate::ScreenOrientationProviderSupported() {
return Shell::GetInstance()
->maximize_mode_controller()
->IsMaximizeModeWindowManagerEnabled() &&
CommandLine::ForCurrentProcess()->HasSwitch(
switches::kAshEnableTouchViewTesting);
}
void ScreenOrientationDelegate::Unlock(content::WebContents* web_contents) {
aura::Window* requesting_window = web_contents->GetNativeView();
if (requesting_window != locking_window_)
return;
locking_window_ = NULL;
Shell::GetInstance()->maximize_mode_controller()->SetRotationLocked(false);
}
void ScreenOrientationDelegate::LockRotationToPrimaryOrientation(
blink::WebScreenOrientationLockType lock_orientation) {
Shell::GetInstance()->maximize_mode_controller()->LockRotation(
natural_orientation_ == lock_orientation ? gfx::Display::ROTATE_0
: gfx::Display::ROTATE_90);
}
void ScreenOrientationDelegate::LockRotationToSecondaryOrientation(
blink::WebScreenOrientationLockType lock_orientation) {
Shell::GetInstance()->maximize_mode_controller()->LockRotation(
natural_orientation_ == lock_orientation ? gfx::Display::ROTATE_180
: gfx::Display::ROTATE_270);
}
void ScreenOrientationDelegate::LockToRotationMatchingOrientation(
blink::WebScreenOrientationLockType lock_orientation) {
// TODO(jonross): Update MaximizeModeController to allow rotation between
// two angles of an orientation (e.g. from ROTATE_0 to ROTATE_180, and from
// ROTATE_90 to ROTATE_270)
DisplayManager* display_manager = Shell::GetInstance()->display_manager();
if (!display_manager->HasInternalDisplay())
return;
gfx::Display::Rotation rotation =
display_manager->GetDisplayInfo(gfx::Display::InternalDisplayId())
.rotation();
MaximizeModeController* controller =
Shell::GetInstance()->maximize_mode_controller();
if (natural_orientation_ == lock_orientation) {
if (rotation == gfx::Display::ROTATE_0 ||
rotation == gfx::Display::ROTATE_180) {
controller->SetRotationLocked(true);
} else {
controller->LockRotation(gfx::Display::ROTATE_0);
}
} else {
if (rotation == gfx::Display::ROTATE_90 ||
rotation == gfx::Display::ROTATE_270) {
controller->SetRotationLocked(true);
} else {
controller->LockRotation(gfx::Display::ROTATE_90);
}
}
}
} // namespace ash

@ -0,0 +1,64 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_CONTENT_DISPLAY_SCREEN_ORIENTATION_DELEGATE_CHROMEOS_H_
#define ASH_CONTENT_DISPLAY_SCREEN_ORIENTATION_DELEGATE_CHROMEOS_H_
#include "base/macros.h"
#include "content/public/browser/screen_orientation_delegate.h"
#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
namespace aura {
class Window;
}
namespace content {
class WebContents;
}
namespace ash {
// Implements ChromeOS specific functionality for ScreenOrientationProvider.
class ScreenOrientationDelegate : public content::ScreenOrientationDelegate {
public:
ScreenOrientationDelegate();
virtual ~ScreenOrientationDelegate();
// content::ScreenOrientationDelegate:
bool FullScreenRequired(content::WebContents* web_contents) override;
void Lock(content::WebContents* web_contents,
blink::WebScreenOrientationLockType lock_orientation) override;
bool ScreenOrientationProviderSupported() override;
void Unlock(content::WebContents* web_contents) override;
private:
// Locks rotation to the angle matching the primary orientation for
// |lock_orientation|.
void LockRotationToPrimaryOrientation(
blink::WebScreenOrientationLockType lock_orientation);
// Locks rotation to the angle matching the secondary orientation for
// |lock_orientation|.
void LockRotationToSecondaryOrientation(
blink::WebScreenOrientationLockType lock_orientation);
// For orientations that do not specify primary or secondary, locks to the
// current rotation if it matches |lock_orientation|. Otherwise locks to a
// matching rotation.
void LockToRotationMatchingOrientation(
blink::WebScreenOrientationLockType lock_orientation);
// The window that has applied the current lock. No other window can apply a
// lock until the current window unlocks rotation.
aura::Window* locking_window_;
// The orientation of the display when at a rotation of 0.
blink::WebScreenOrientationLockType natural_orientation_;
DISALLOW_COPY_AND_ASSIGN(ScreenOrientationDelegate);
};
} // namespace ash
#endif // ASH_CONTENT_DISPLAY_SCREEN_ORIENTATION_DELEGATE_CHROMEOS_H_

@ -0,0 +1,194 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/ash_switches.h"
#include "ash/content/display/screen_orientation_delegate_chromeos.h"
#include "ash/display/display_info.h"
#include "ash/display/display_manager.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/ash_test_helper.h"
#include "ash/test/test_shell_delegate.h"
#include "ash/wm/maximize_mode/maximize_mode_controller.h"
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_browser_context.h"
#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
#include "ui/gfx/display.h"
#include "ui/views/test/webview_test_helper.h"
#include "ui/views/view.h"
#include "ui/views/views_delegate.h"
namespace ash {
namespace {
gfx::Display::Rotation Rotation() {
return Shell::GetInstance()
->display_manager()
->GetDisplayInfo(gfx::Display::InternalDisplayId())
.rotation();
}
bool RotationLocked() {
return Shell::GetInstance()->maximize_mode_controller()->rotation_locked();
}
} // namespace
class ScreenOrientationDelegateTest : public test::AshTestBase {
public:
ScreenOrientationDelegateTest();
virtual ~ScreenOrientationDelegateTest();
ScreenOrientationDelegate* delegate() { return screen_orientation_delegate_; }
// Creates and initializes and empty content::WebContents that is backed by a
// content::BrowserContext and that has an aura::Window.
content::WebContents* CreateWebContents();
// Creates a secondary content::WebContents, with a separate
// content::BrowserContext.
content::WebContents* CreateSecondaryWebContents();
// test::AshTestBase:
void SetUp() override;
private:
ScreenOrientationDelegate* screen_orientation_delegate_;
// Optional content::BrowserContext used for two window tests.
scoped_ptr<content::BrowserContext> secondary_browser_context_;
// Setups underlying content layer so that content::WebContents can be
// generated.
scoped_ptr<views::WebViewTestHelper> webview_test_helper_;
DISALLOW_COPY_AND_ASSIGN(ScreenOrientationDelegateTest);
};
ScreenOrientationDelegateTest::ScreenOrientationDelegateTest() {
webview_test_helper_.reset(new views::WebViewTestHelper());
}
ScreenOrientationDelegateTest::~ScreenOrientationDelegateTest() {
}
content::WebContents* ScreenOrientationDelegateTest::CreateWebContents() {
return views::ViewsDelegate::views_delegate->CreateWebContents(
ash_test_helper()->test_shell_delegate()->GetActiveBrowserContext(),
nullptr);
}
content::WebContents*
ScreenOrientationDelegateTest::CreateSecondaryWebContents() {
secondary_browser_context_.reset(new content::TestBrowserContext());
return views::ViewsDelegate::views_delegate->CreateWebContents(
secondary_browser_context_.get(), nullptr);
}
void ScreenOrientationDelegateTest::SetUp() {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kAshUseFirstDisplayAsInternal);
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kAshEnableTouchViewTesting);
test::AshTestBase::SetUp();
screen_orientation_delegate_ =
Shell::GetInstance()->screen_orientation_delegate();
}
// Tests that a content::WebContents can lock rotation.
TEST_F(ScreenOrientationDelegateTest, LockOrientation) {
scoped_ptr<content::WebContents> content(CreateWebContents());
ASSERT_NE(nullptr, content->GetNativeView());
ASSERT_EQ(gfx::Display::ROTATE_0, Rotation());
ASSERT_FALSE(RotationLocked());
delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape);
EXPECT_EQ(gfx::Display::ROTATE_0, Rotation());
EXPECT_TRUE(RotationLocked());
}
// Tests that a content::WebContents can unlock rotation.
TEST_F(ScreenOrientationDelegateTest, Unlock) {
scoped_ptr<content::WebContents> content(CreateWebContents());
ASSERT_NE(nullptr, content->GetNativeView());
ASSERT_EQ(gfx::Display::ROTATE_0, Rotation());
ASSERT_FALSE(RotationLocked());
delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape);
EXPECT_EQ(gfx::Display::ROTATE_0, Rotation());
EXPECT_TRUE(RotationLocked());
delegate()->Unlock(content.get());
EXPECT_FALSE(RotationLocked());
}
// Tests that a content::WebContents is able to change the orientation of the
// display after having locked rotation.
TEST_F(ScreenOrientationDelegateTest, OrientationChanges) {
scoped_ptr<content::WebContents> content(CreateWebContents());
ASSERT_NE(nullptr, content->GetNativeView());
ASSERT_EQ(gfx::Display::ROTATE_0, Rotation());
ASSERT_FALSE(RotationLocked());
delegate()->Lock(content.get(), blink::WebScreenOrientationLockPortrait);
EXPECT_EQ(gfx::Display::ROTATE_90, Rotation());
EXPECT_TRUE(RotationLocked());
delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape);
EXPECT_EQ(gfx::Display::ROTATE_0, Rotation());
}
// Tests that a user initiated rotation lock cannot be unlocked by a
// content::WebContents.
TEST_F(ScreenOrientationDelegateTest, UserLockRejectsUnlock) {
Shell::GetInstance()->maximize_mode_controller()->SetRotationLocked(true);
scoped_ptr<content::WebContents> content(CreateWebContents());
delegate()->Unlock(content.get());
EXPECT_TRUE(RotationLocked());
}
// Tests that orientation can only be set by the first content::WebContents that
// has set a rotation lock.
TEST_F(ScreenOrientationDelegateTest, SecondContentCannotChangeOrientation) {
scoped_ptr<content::WebContents> content1(CreateWebContents());
scoped_ptr<content::WebContents> content2(CreateSecondaryWebContents());
ASSERT_NE(content1->GetNativeView(), content2->GetNativeView());
delegate()->Lock(content1.get(), blink::WebScreenOrientationLockLandscape);
delegate()->Lock(content2.get(), blink::WebScreenOrientationLockPortrait);
EXPECT_EQ(gfx::Display::ROTATE_0, Rotation());
}
// Tests that only the content::WebContents that set a rotation lock can perform
// an unlock.
TEST_F(ScreenOrientationDelegateTest, SecondContentCannotUnlock) {
scoped_ptr<content::WebContents> content1(CreateWebContents());
scoped_ptr<content::WebContents> content2(CreateSecondaryWebContents());
ASSERT_NE(content1->GetNativeView(), content2->GetNativeView());
delegate()->Lock(content1.get(), blink::WebScreenOrientationLockLandscape);
delegate()->Unlock(content2.get());
EXPECT_TRUE(RotationLocked());
}
// Tests that alternate content::WebContents can set a rotation lock after a
// preexisting lock has been released.
TEST_F(ScreenOrientationDelegateTest, AfterUnlockSecondContentCanLock) {
scoped_ptr<content::WebContents> content1(CreateWebContents());
scoped_ptr<content::WebContents> content2(CreateSecondaryWebContents());
ASSERT_NE(content1->GetNativeView(), content2->GetNativeView());
delegate()->Lock(content1.get(), blink::WebScreenOrientationLockLandscape);
delegate()->Unlock(content1.get());
delegate()->Lock(content2.get(), blink::WebScreenOrientationLockPortrait);
EXPECT_EQ(gfx::Display::ROTATE_90, Rotation());
EXPECT_TRUE(RotationLocked());
}
} // namespace ash

@ -121,6 +121,7 @@
#include "ui/gfx/x/x11_types.h"
#endif // defined(USE_X11)
#include "ash/ash_constants.h"
#include "ash/content/display/screen_orientation_delegate_chromeos.h"
#include "ash/display/display_change_observer_chromeos.h"
#include "ash/display/display_configurator_animation.h"
#include "ash/display/display_error_observer_chromeos.h"
@ -1060,6 +1061,7 @@ void Shell::Init(const ShellInitParams& init_params) {
new VideoActivityNotifier(video_detector_.get()));
bluetooth_notification_controller_.reset(new BluetoothNotificationController);
last_window_closed_logout_reminder_.reset(new LastWindowClosedLogoutReminder);
screen_orientation_delegate_.reset(new ScreenOrientationDelegate());
#endif
// The compositor thread and main message loop have to be running in
// order to create mirror window. Run it after the main message loop

@ -118,6 +118,7 @@ class ResolutionNotificationController;
class RootWindowController;
class ScopedTargetRootWindow;
class ScreenAsh;
class ScreenOrientationDelegate;
class ScreenPositionController;
class SessionStateDelegate;
class Shelf;
@ -535,6 +536,10 @@ class ASH_EXPORT Shell : public SystemModalContainerEventFilterDelegate,
return logout_confirmation_controller_.get();
}
ScreenOrientationDelegate* screen_orientation_delegate() {
return screen_orientation_delegate_.get();
}
VirtualKeyboardController* virtual_keyboard_controller() {
return virtual_keyboard_controller_.get();
}
@ -728,6 +733,9 @@ class ASH_EXPORT Shell : public SystemModalContainerEventFilterDelegate,
// Listens for output changes and updates the display manager.
scoped_ptr<DisplayChangeObserver> display_change_observer_;
// Implements content::ScreenOrientationDelegate for ChromeOS
scoped_ptr<ScreenOrientationDelegate> screen_orientation_delegate_;
scoped_ptr<TouchTransformerController> touch_transformer_controller_;
#if defined(USE_X11)

@ -153,6 +153,11 @@ void MaximizeModeController::SetRotationLocked(bool rotation_locked) {
OnRotationLockChanged(rotation_locked_));
}
void MaximizeModeController::LockRotation(gfx::Display::Rotation rotation) {
SetRotationLocked(true);
SetDisplayRotation(Shell::GetInstance()->display_manager(), rotation);
}
void MaximizeModeController::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}

@ -76,6 +76,11 @@ class ASH_EXPORT MaximizeModeController
// change the display rotation.
void SetRotationLocked(bool rotation_locked);
// Sets the display rotation to |rotation| and prevents future calls to
// OnAccelerometerUpdated from changing the rotation. SetRotationLocked(false)
// removes the rotation lock.
void LockRotation(gfx::Display::Rotation rotation);
// Add/Remove observers.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);

@ -42,6 +42,7 @@ bool ScreenOrientationDelegateAndroid::FullScreenRequired(
}
void ScreenOrientationDelegateAndroid::Lock(
WebContents* web_contents,
blink::WebScreenOrientationLockType lock_orientation) {
Java_ScreenOrientationProvider_lockOrientation(
base::android::AttachCurrentThread(), lock_orientation);
@ -52,7 +53,7 @@ bool ScreenOrientationDelegateAndroid::ScreenOrientationProviderSupported() {
return true;
}
void ScreenOrientationDelegateAndroid::Unlock() {
void ScreenOrientationDelegateAndroid::Unlock(WebContents* web_contents) {
Java_ScreenOrientationProvider_unlockOrientation(
base::android::AttachCurrentThread());
}

@ -35,11 +35,11 @@ class ScreenOrientationDelegateAndroid : public ScreenOrientationDelegate {
static void StopAccurateListening();
// ScreenOrientationDelegate:
virtual bool FullScreenRequired(WebContents* web_contents) override;
virtual void Lock(
blink::WebScreenOrientationLockType lock_orientation) override;
virtual bool ScreenOrientationProviderSupported() override;
virtual void Unlock() override;
bool FullScreenRequired(WebContents* web_contents) override;
void Lock(WebContents* web_contents,
blink::WebScreenOrientationLockType lock_orientation) override;
bool ScreenOrientationProviderSupported() override;
void Unlock(WebContents* web_contents) override;
private:
DISALLOW_COPY_AND_ASSIGN(ScreenOrientationDelegateAndroid);

@ -25,13 +25,14 @@ class CONTENT_EXPORT ScreenOrientationDelegate {
virtual bool FullScreenRequired(WebContents* web_contents) = 0;
// Lock display to the given orientation.
virtual void Lock(blink::WebScreenOrientationLockType lock_orientation) = 0;
virtual void Lock(WebContents* web_contents,
blink::WebScreenOrientationLockType lock_orientation) = 0;
// Are ScreenOrientationProvider requests currently supported by the platform.
virtual bool ScreenOrientationProviderSupported() = 0;
// Unlocks the display, allowing hardware rotation to resume.
virtual void Unlock() = 0;
virtual void Unlock(WebContents* web_contents) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(ScreenOrientationDelegate);

@ -73,7 +73,7 @@ void ScreenOrientationProvider::LockOrientation(int request_id,
}
lock_applied_ = true;
delegate_->Lock(lock_orientation);
delegate_->Lock(web_contents(), lock_orientation);
// If two calls happen close to each other some platforms will ignore the
// first. A successful lock will be once orientation matches the latest
@ -94,7 +94,7 @@ void ScreenOrientationProvider::UnlockOrientation() {
if (!lock_applied_ || !delegate_)
return;
delegate_->Unlock();
delegate_->Unlock(web_contents());
lock_applied_ = false;
pending_lock_.reset();