This source file includes following definitions.
- AngleBetweenVectorsInDegrees
- ClockwiseAngleBetweenVectorsInDegrees
- OnAccelerometerUpdated
- HandleHingeRotation
- HandleScreenRotation
#include "ash/wm/maximize_mode/maximize_mode_controller.h"
#include "ash/accelerometer/accelerometer_controller.h"
#include "ash/display/display_manager.h"
#include "ash/shell.h"
#include "ui/gfx/vector3d_f.h"
namespace ash {
namespace {
const float kEnterMaximizeModeAngle = 200.0f;
const float kExitMaximizeModeAngle = 160.0f;
const float kFullyOpenAngleErrorTolerance = 10.0f;
const float kHingeAxisAlignedThreshold = 15.0f;
const float kDisplayRotationStickyAngleDegrees = 60.0f;
const float kMinimumAccelerationScreenRotation = 0.3f;
const float kRadiansToDegrees = 180.0f / 3.14159265f;
float AngleBetweenVectorsInDegrees(const gfx::Vector3dF& base,
const gfx::Vector3dF& other) {
return acos(gfx::DotProduct(base, other) /
base.Length() / other.Length()) * kRadiansToDegrees;
}
float ClockwiseAngleBetweenVectorsInDegrees(const gfx::Vector3dF& base,
const gfx::Vector3dF& other,
const gfx::Vector3dF& normal) {
float angle = AngleBetweenVectorsInDegrees(base, other);
gfx::Vector3dF cross(base);
cross.Cross(other);
if (gfx::DotProduct(cross, normal) > 0.0f)
angle = 360.0f - angle;
return angle;
}
}
MaximizeModeController::MaximizeModeController() {
Shell::GetInstance()->accelerometer_controller()->AddObserver(this);
}
MaximizeModeController::~MaximizeModeController() {
Shell::GetInstance()->accelerometer_controller()->RemoveObserver(this);
}
void MaximizeModeController::OnAccelerometerUpdated(
const gfx::Vector3dF& base,
const gfx::Vector3dF& lid) {
HandleHingeRotation(base, lid);
HandleScreenRotation(lid);
}
void MaximizeModeController::HandleHingeRotation(const gfx::Vector3dF& base,
const gfx::Vector3dF& lid) {
static const gfx::Vector3dF hinge_vector(0.0f, 1.0f, 0.0f);
bool maximize_mode_engaged =
Shell::GetInstance()->IsMaximizeModeWindowManagerEnabled();
float hinge_angle = AngleBetweenVectorsInDegrees(base, hinge_vector);
if (hinge_angle < kHingeAxisAlignedThreshold ||
hinge_angle > 180.0f - kHingeAxisAlignedThreshold) {
return;
}
float angle = ClockwiseAngleBetweenVectorsInDegrees(base, lid, hinge_vector);
if (maximize_mode_engaged &&
angle > kFullyOpenAngleErrorTolerance &&
angle < kExitMaximizeModeAngle) {
Shell::GetInstance()->EnableMaximizeModeWindowManager(false);
} else if (!maximize_mode_engaged &&
angle > kEnterMaximizeModeAngle) {
Shell::GetInstance()->EnableMaximizeModeWindowManager(true);
}
}
void MaximizeModeController::HandleScreenRotation(const gfx::Vector3dF& lid) {
bool maximize_mode_engaged =
Shell::GetInstance()->IsMaximizeModeWindowManagerEnabled();
DisplayManager* display_manager =
Shell::GetInstance()->display_manager();
gfx::Display::Rotation current_rotation = display_manager->GetDisplayInfo(
gfx::Display::InternalDisplayId()).rotation();
if (!maximize_mode_engaged) {
if (current_rotation != gfx::Display::ROTATE_0) {
display_manager->SetDisplayRotation(gfx::Display::InternalDisplayId(),
gfx::Display::ROTATE_0);
}
return;
}
gfx::Vector3dF lid_flattened(lid.x(), lid.y(), 0.0f);
float lid_flattened_length = lid_flattened.Length();
if (lid_flattened_length < kMinimumAccelerationScreenRotation)
return;
static gfx::Vector3dF rotation_reference(-1.0f, 1.0f, 0.0f);
gfx::Vector3dF down(0.0f, 0.0f, 0.0f);
if (current_rotation == gfx::Display::ROTATE_0)
down.set_x(-1.0f);
else if (current_rotation == gfx::Display::ROTATE_90)
down.set_y(1.0f);
else if (current_rotation == gfx::Display::ROTATE_180)
down.set_x(1.0f);
else
down.set_y(-1.0f);
if (AngleBetweenVectorsInDegrees(down, lid_flattened) <
kDisplayRotationStickyAngleDegrees) {
return;
}
float angle = ClockwiseAngleBetweenVectorsInDegrees(rotation_reference,
lid_flattened, gfx::Vector3dF(0.0f, 0.0f, -1.0f));
gfx::Display::Rotation new_rotation = gfx::Display::ROTATE_90;
if (angle < 90.0f)
new_rotation = gfx::Display::ROTATE_0;
else if (angle < 180.0f)
new_rotation = gfx::Display::ROTATE_270;
else if (angle < 270.0f)
new_rotation = gfx::Display::ROTATE_180;
if (new_rotation == gfx::Display::ROTATE_0 ||
maximize_mode_engaged) {
display_manager->SetDisplayRotation(gfx::Display::InternalDisplayId(),
new_rotation);
}
}
}