Skip to content

Commit

Permalink
Make screen.orientation.angle relative to the display panel's natural…
Browse files Browse the repository at this point in the history
… orientation

This CL updates the screen.orientation.angle web API to output relative to the
device panel. screen.orientation.angle is used by web apps using a desynchronised
WebGL canvas to achieve low latency performance via hardware overlays. This
requires alignment with the device output panel.

Fixed: 998131
Test: PanelRotationBrowserTest.ScreenOrientationAPI
Change-Id: I05efbfb8aecd5015b18f0e4f434ab67df6ca50b6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1911344
Commit-Queue: Alan Cutter <alancutter@chromium.org>
Auto-Submit: Alan Cutter <alancutter@chromium.org>
Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
Reviewed-by: Ken Buchanan <kenrb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#716876}
  • Loading branch information
alancutter authored and Commit Bot committed Nov 20, 2019
1 parent 56b806c commit 4cfd0c5
Show file tree
Hide file tree
Showing 14 changed files with 124 additions and 31 deletions.
9 changes: 6 additions & 3 deletions content/browser/renderer_host/display_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@ void DisplayUtil::DisplayToScreenInfo(ScreenInfo* screen_info,
screen_info->is_monochrome = display.is_monochrome();
screen_info->display_frequency = display.display_frequency();

screen_info->orientation_angle = display.RotationAsDegree();
// TODO(https://crbug.com/998131): Expose panel orientation via a proper web
// API instead of window.screen.orientation.angle.
screen_info->orientation_angle = display.PanelRotationAsDegree();
#if defined(USE_AURA)
// The Display rotation and the ScreenInfo orientation are not the same
// angle. The former is the physical display rotation while the later is the
// rotation required by the content to be shown properly on the screen, in
// other words, relative to the physical display.
// Spec: https://w3c.github.io/screen-orientation/#dom-screenorientation-angle
// TODO(ccameron): Should this apply to macOS? Should this be reconciled at a
// higher level (say, in conversion to WebScreenInfo)?
if (screen_info->orientation_angle == 90)
Expand Down Expand Up @@ -84,7 +87,7 @@ void DisplayUtil::GetNativeViewScreenInfo(ScreenInfo* screen_info,
// static
ScreenOrientationValues DisplayUtil::GetOrientationTypeForMobile(
const display::Display& display) {
int angle = display.RotationAsDegree();
int angle = display.PanelRotationAsDegree();
const gfx::Rect& bounds = display.bounds();

// Whether the device's natural orientation is portrait.
Expand Down Expand Up @@ -119,7 +122,7 @@ ScreenOrientationValues DisplayUtil::GetOrientationTypeForDesktop(
static int primary_landscape_angle = -1;
static int primary_portrait_angle = -1;

int angle = display.RotationAsDegree();
int angle = display.PanelRotationAsDegree();
const gfx::Rect& bounds = display.bounds();
bool is_portrait = bounds.height() >= bounds.width();

Expand Down
44 changes: 44 additions & 0 deletions content/browser/renderer_host/panel_rotation_browsertest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2019 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 "base/strings/stringprintf.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/shell/browser/shell.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"

namespace content {

// TODO(https://crbug.com/998131): Add test coverage across all platforms.
#if defined(OS_CHROMEOS)
class PanelRotationBrowserTest : public ContentBrowserTest {
protected:
void SetPanelRotation(display::Display::Rotation rotation) {
display::Screen* screen = display::Screen::GetScreen();
screen->SetPanelRotationForTesting(screen->GetPrimaryDisplay().id(),
rotation);
}
int ReadScreenOrientationAngle() {
return EvalJs(CreateBrowser()->web_contents(), "screen.orientation.angle")
.ExtractInt();
}
};

IN_PROC_BROWSER_TEST_F(PanelRotationBrowserTest, ScreenOrientationAPI) {
SetPanelRotation(display::Display::ROTATE_0);
EXPECT_EQ(ReadScreenOrientationAngle(), 0);

SetPanelRotation(display::Display::ROTATE_90);
EXPECT_EQ(ReadScreenOrientationAngle(), 270);

SetPanelRotation(display::Display::ROTATE_180);
EXPECT_EQ(ReadScreenOrientationAngle(), 180);

SetPanelRotation(display::Display::ROTATE_270);
EXPECT_EQ(ReadScreenOrientationAngle(), 90);
}
#endif // defined(OS_CHROMEOS)

} // namespace content
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ namespace content {

namespace {

display::Display CreateDisplay(int width, int height, int angle) {
display::Display CreateDisplay(int width,
int height,
display::Display::Rotation rotation) {
display::Display display;
display.SetRotationAsDegree(angle);
display.set_panel_rotation(rotation);
display.set_bounds(gfx::Rect(width, height));

return display;
Expand All @@ -26,57 +28,58 @@ display::Display CreateDisplay(int width, int height, int angle) {
TEST(RenderWidgetHostViewBaseTest, OrientationTypeForMobile) {
// Square display (width == height).
{
display::Display display = CreateDisplay(100, 100, 0);
display::Display display =
CreateDisplay(100, 100, display::Display::ROTATE_0);
EXPECT_EQ(SCREEN_ORIENTATION_VALUES_PORTRAIT_PRIMARY,
DisplayUtil::GetOrientationTypeForMobile(display));

display = CreateDisplay(200, 200, 90);
display = CreateDisplay(200, 200, display::Display::ROTATE_90);
EXPECT_EQ(SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY,
DisplayUtil::GetOrientationTypeForMobile(display));

display = CreateDisplay(0, 0, 180);
display = CreateDisplay(0, 0, display::Display::ROTATE_180);
EXPECT_EQ(SCREEN_ORIENTATION_VALUES_PORTRAIT_SECONDARY,
DisplayUtil::GetOrientationTypeForMobile(display));

display = CreateDisplay(10000, 10000, 270);
display = CreateDisplay(10000, 10000, display::Display::ROTATE_270);
EXPECT_EQ(SCREEN_ORIENTATION_VALUES_LANDSCAPE_SECONDARY,
DisplayUtil::GetOrientationTypeForMobile(display));
}

// natural width > natural height.
{
display::Display display = CreateDisplay(1, 0, 0);
display::Display display = CreateDisplay(1, 0, display::Display::ROTATE_0);
EXPECT_EQ(SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY,
DisplayUtil::GetOrientationTypeForMobile(display));

display = CreateDisplay(19999, 20000, 90);
display = CreateDisplay(19999, 20000, display::Display::ROTATE_90);
EXPECT_EQ(SCREEN_ORIENTATION_VALUES_PORTRAIT_SECONDARY,
DisplayUtil::GetOrientationTypeForMobile(display));

display = CreateDisplay(200, 100, 180);
display = CreateDisplay(200, 100, display::Display::ROTATE_180);
EXPECT_EQ(SCREEN_ORIENTATION_VALUES_LANDSCAPE_SECONDARY,
DisplayUtil::GetOrientationTypeForMobile(display));

display = CreateDisplay(1, 10000, 270);
display = CreateDisplay(1, 10000, display::Display::ROTATE_270);
EXPECT_EQ(SCREEN_ORIENTATION_VALUES_PORTRAIT_PRIMARY,
DisplayUtil::GetOrientationTypeForMobile(display));
}

// natural width < natural height.
{
display::Display display = CreateDisplay(0, 1, 0);
display::Display display = CreateDisplay(0, 1, display::Display::ROTATE_0);
EXPECT_EQ(SCREEN_ORIENTATION_VALUES_PORTRAIT_PRIMARY,
DisplayUtil::GetOrientationTypeForMobile(display));

display = CreateDisplay(20000, 19999, 90);
display = CreateDisplay(20000, 19999, display::Display::ROTATE_90);
EXPECT_EQ(SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY,
DisplayUtil::GetOrientationTypeForMobile(display));

display = CreateDisplay(100, 200, 180);
display = CreateDisplay(100, 200, display::Display::ROTATE_180);
EXPECT_EQ(SCREEN_ORIENTATION_VALUES_PORTRAIT_SECONDARY,
DisplayUtil::GetOrientationTypeForMobile(display));

display = CreateDisplay(10000, 1, 270);
display = CreateDisplay(10000, 1, display::Display::ROTATE_270);
EXPECT_EQ(SCREEN_ORIENTATION_VALUES_LANDSCAPE_SECONDARY,
DisplayUtil::GetOrientationTypeForMobile(display));
}
Expand All @@ -91,27 +94,27 @@ TEST(RenderWidgetHostViewBaseTest, OrientationTypeForDesktop) {

// natural width > natural height.
{
display::Display display = CreateDisplay(1, 0, 0);
display::Display display = CreateDisplay(1, 0, display::Display::ROTATE_0);
ScreenOrientationValues landscape_1 =
DisplayUtil::GetOrientationTypeForDesktop(display);
EXPECT_TRUE(landscape_1 == SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY ||
landscape_1 == SCREEN_ORIENTATION_VALUES_LANDSCAPE_SECONDARY);

display = CreateDisplay(200, 100, 180);
display = CreateDisplay(200, 100, display::Display::ROTATE_180);
ScreenOrientationValues landscape_2 =
DisplayUtil::GetOrientationTypeForDesktop(display);
EXPECT_TRUE(landscape_2 == SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY ||
landscape_2 == SCREEN_ORIENTATION_VALUES_LANDSCAPE_SECONDARY);

EXPECT_NE(landscape_1, landscape_2);

display = CreateDisplay(19999, 20000, 90);
display = CreateDisplay(19999, 20000, display::Display::ROTATE_90);
ScreenOrientationValues portrait_1 =
DisplayUtil::GetOrientationTypeForDesktop(display);
EXPECT_TRUE(portrait_1 == SCREEN_ORIENTATION_VALUES_PORTRAIT_PRIMARY ||
portrait_1 == SCREEN_ORIENTATION_VALUES_PORTRAIT_SECONDARY);

display = CreateDisplay(1, 10000, 270);
display = CreateDisplay(1, 10000, display::Display::ROTATE_270);
ScreenOrientationValues portrait_2 =
DisplayUtil::GetOrientationTypeForDesktop(display);
EXPECT_TRUE(portrait_2 == SCREEN_ORIENTATION_VALUES_PORTRAIT_PRIMARY ||
Expand Down
1 change: 1 addition & 0 deletions content/test/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,7 @@ test("content_browsertests") {
"../browser/renderer_host/input/wheel_event_listener_browsertest.cc",
"../browser/renderer_host/input/wheel_scroll_latching_browsertest.cc",
"../browser/renderer_host/media/video_capture_browsertest.cc",
"../browser/renderer_host/panel_rotation_browsertest.cc",
"../browser/renderer_host/render_process_host_browsertest.cc",
"../browser/renderer_host/render_view_host_browsertest.cc",
"../browser/renderer_host/render_widget_host_browsertest.cc",
Expand Down
23 changes: 22 additions & 1 deletion ui/display/display.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,21 @@ gfx::ColorSpace ForcedColorProfileStringToColorSpace(const std::string& value) {
return gfx::ColorSpace::CreateSRGB();
}

const char* ToRotationString(display::Display::Rotation rotation) {
switch (rotation) {
case display::Display::ROTATE_0:
return "0";
case display::Display::ROTATE_90:
return "90";
case display::Display::ROTATE_180:
return "180";
case display::Display::ROTATE_270:
return "270";
}
NOTREACHED();
return "unkonwn";
}

} // namespace

bool CompareDisplayIds(int64_t id1, int64_t id2) {
Expand Down Expand Up @@ -266,6 +281,10 @@ void Display::SetRotationAsDegree(int rotation) {
}
}

int Display::PanelRotationAsDegree() const {
return RotationToDegrees(panel_rotation_);
}

// static
gfx::Transform Display::GetRotationTransform(Rotation rotation,
const gfx::SizeF& size) {
Expand Down Expand Up @@ -357,9 +376,11 @@ gfx::Size Display::GetSizeInPixel() const {

std::string Display::ToString() const {
return base::StringPrintf(
"Display[%lld] bounds=[%s], workarea=[%s], scale=%g, %s.",
"Display[%lld] bounds=[%s], workarea=[%s], scale=%g, rotation=%s, "
"panel_rotation=%s %s.",
static_cast<long long int>(id_), bounds_.ToString().c_str(),
work_area_.ToString().c_str(), device_scale_factor_,
ToRotationString(rotation_), ToRotationString(panel_rotation_),
IsInternal() ? "internal" : "external");
}

Expand Down
6 changes: 6 additions & 0 deletions ui/display/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@ class DISPLAY_EXPORT Display final {
int RotationAsDegree() const;
void SetRotationAsDegree(int rotation);

// Panel's native rotation. This is same as |rotation()| in normal case.
Rotation panel_rotation() const { return panel_rotation_; }
void set_panel_rotation(Rotation rotation) { panel_rotation_ = rotation; }
int PanelRotationAsDegree() const;

// Returns an exact matrix representation of the transform that corrects for
// the display's rotation.
static gfx::Transform GetRotationTransform(Rotation rotation,
Expand Down Expand Up @@ -292,6 +297,7 @@ class DISPLAY_EXPORT Display final {
gfx::Rect work_area_;
float device_scale_factor_;
Rotation rotation_ = ROTATE_0;
Rotation panel_rotation_ = ROTATE_0;
TouchSupport touch_support_ = TouchSupport::UNKNOWN;
AccelerometerSupport accelerometer_support_ = AccelerometerSupport::UNKNOWN;
gfx::Size maximum_cursor_size_;
Expand Down
4 changes: 4 additions & 0 deletions ui/display/display_list.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ uint32_t DisplayList::UpdateDisplay(const Display& display, Type type) {
local_display->set_rotation(display.rotation());
changed_values |= DisplayObserver::DISPLAY_METRIC_ROTATION;
}
if (local_display->panel_rotation() != display.panel_rotation()) {
local_display->set_panel_rotation(display.panel_rotation());
changed_values |= DisplayObserver::DISPLAY_METRIC_ROTATION;
}
if (local_display->device_scale_factor() != display.device_scale_factor()) {
local_display->set_device_scale_factor(display.device_scale_factor());
changed_values |= DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR;
Expand Down
1 change: 1 addition & 0 deletions ui/display/manager/display_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2038,6 +2038,7 @@ Display DisplayManager::CreateDisplayFromDisplayInfoById(int64_t id) {
new_display.SetScaleAndBounds(device_scale_factor,
gfx::Rect(bounds_in_native.size()));
new_display.set_rotation(display_info.GetActiveRotation());
new_display.set_panel_rotation(display_info.GetLogicalActiveRotation());
new_display.set_touch_support(display_info.touch_support());
new_display.set_maximum_cursor_size(display_info.maximum_cursor_size());
new_display.SetColorSpaceAndDepth(display_info.color_space());
Expand Down
4 changes: 0 additions & 4 deletions ui/display/manager/managed_display_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,6 @@ Display::Rotation ManagedDisplayInfo::GetLogicalActiveRotation() const {
GetRotation(Display::RotationSource::ACTIVE));
}

Display::Rotation ManagedDisplayInfo::GetNaturalOrientationRotation() const {
return GetRotationWithPanelOrientation(Display::ROTATE_0);
}

Display::Rotation ManagedDisplayInfo::GetRotation(
Display::RotationSource source) const {
if (rotations_.find(source) == rotations_.end())
Expand Down
4 changes: 0 additions & 4 deletions ui/display/manager/managed_display_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,6 @@ class DISPLAY_MANAGER_EXPORT ManagedDisplayInfo {
// orientation adjustment applied.
Display::Rotation GetLogicalActiveRotation() const;

// Returns the natural orientation rotation with the panel orientation
// adjustment applied.
Display::Rotation GetNaturalOrientationRotation() const;

// Returns the source which set the active rotation for this display.
Display::RotationSource active_rotation_source() const {
return active_rotation_source_;
Expand Down
6 changes: 6 additions & 0 deletions ui/display/screen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,10 @@ bool Screen::GetDisplayWithDisplayId(int64_t display_id,
return false;
}

void Screen::SetPanelRotationForTesting(int64_t display_id,
Display::Rotation rotation) {
// Not implemented.
DCHECK(false);
}

} // namespace display
5 changes: 4 additions & 1 deletion ui/display/screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <vector>

#include "base/macros.h"
#include "ui/display/display.h"
#include "ui/display/display_export.h"
#include "ui/gfx/native_widget_types.h"

Expand All @@ -17,7 +18,6 @@ class Rect;
}

namespace display {
class Display;
class DisplayObserver;

// A utility class for getting various info about screen size, displays,
Expand Down Expand Up @@ -104,6 +104,9 @@ class DISPLAY_EXPORT Screen {
// untouched.
bool GetDisplayWithDisplayId(int64_t display_id, Display* display) const;

virtual void SetPanelRotationForTesting(int64_t display_id,
Display::Rotation rotation);

private:
static gfx::NativeWindow GetWindowForView(gfx::NativeView view);

Expand Down
7 changes: 7 additions & 0 deletions ui/display/screen_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ void ScreenBase::RemoveObserver(DisplayObserver* observer) {
display_list_.RemoveObserver(observer);
}

void ScreenBase::SetPanelRotationForTesting(int64_t display_id,
Display::Rotation rotation) {
Display display = *display_list_.FindDisplayById(display_id);
display.set_panel_rotation(rotation);
ProcessDisplayChanged(display, true);
}

void ScreenBase::ProcessDisplayChanged(const Display& changed_display,
bool is_primary) {
if (display_list_.FindDisplayById(changed_display.id()) ==
Expand Down
2 changes: 2 additions & 0 deletions ui/display/screen_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class DISPLAY_EXPORT ScreenBase : public Screen {
Display GetDisplayMatching(const gfx::Rect& match_rect) const override;
void AddObserver(DisplayObserver* observer) override;
void RemoveObserver(DisplayObserver* observer) override;
void SetPanelRotationForTesting(int64_t display_id,
Display::Rotation rotation) override;

protected:
// Invoked when a display changed in some way, including being added.
Expand Down

0 comments on commit 4cfd0c5

Please sign in to comment.