Commit 6bb9fbc7 authored by Roman Aleksandrov's avatar Roman Aleksandrov Committed by Commit Bot

Lock Screen: Show auth error and info bubble on sides of the text field.

Change behavior of auth error bubble and smart lock info bubble to make
them appear on the right and left side.
Make bubbles adjust to the height of virtual keyboard and tray.

Bug: 888696
Change-Id: I882832b892e762db69708a65f4f2dd6063d0ef59
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1863093
Commit-Queue: Roman Aleksandrov <raleksandrov@google.com>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#709982}
parent 86af7333
......@@ -1773,6 +1773,7 @@ test("ash_unittests") {
"login/ui/login_user_view_unittest.cc",
"login/ui/note_action_launch_button_unittest.cc",
"login/ui/parent_access_view_unittest.cc",
"login/ui/views_utils_unittest.cc",
"magnifier/docked_magnifier_controller_impl_unittest.cc",
"magnifier/magnification_controller_unittest.cc",
"magnifier/magnifier_test_utils.cc",
......
......@@ -96,6 +96,10 @@ constexpr int kMediumDensityMarginLeftOfAuthUserPortraitDp = 0;
constexpr int kMediumDensityDistanceBetweenAuthUserAndUsersLandscapeDp = 220;
constexpr int kMediumDensityDistanceBetweenAuthUserAndUsersPortraitDp = 84;
// Horizontal and vertical padding of auth error bubble.
constexpr int kHorizontalPaddingAuthErrorBubbleDp = 8;
constexpr int kVerticalPaddingAuthErrorBubbleDp = 8;
// Spacing between the auth error text and the learn more button.
constexpr int kLearnMoreButtonVerticalSpacingDp = 6;
......@@ -142,6 +146,40 @@ class AuthErrorLearnMoreButton : public views::Button,
DISALLOW_COPY_AND_ASSIGN(AuthErrorLearnMoreButton);
};
class AuthErrorBubble : public LoginErrorBubble {
public:
AuthErrorBubble() = default;
// ash::LoginBaseBubbleView
gfx::Point CalculatePosition() override {
if (!GetAnchorView())
return gfx::Point();
gfx::Point anchor_position = GetAnchorView()->bounds().origin();
ConvertPointToTarget(GetAnchorView()->parent() /*source*/,
GetAnchorView()->GetWidget()->GetRootView() /*target*/,
&anchor_position);
auto bounds = GetAnchorView()->GetWidget()->GetRootView()->GetLocalBounds();
const int work_area_height =
display::Screen::GetScreen()
->GetDisplayNearestWindow(
GetAnchorView()->GetWidget()->GetNativeWindow())
.work_area()
.height();
bounds.set_height(std::min(bounds.height(), work_area_height));
gfx::Size bubble_size(width() + 2 * kHorizontalPaddingAuthErrorBubbleDp,
height() + kVerticalPaddingAuthErrorBubbleDp);
auto result = login_views_utils::CalculateBubblePositionRigthLeftStrategy(
{anchor_position, GetAnchorView()->size()}, bubble_size, bounds);
// Get position of the bubble surrounded by paddings.
result.Offset(kHorizontalPaddingAuthErrorBubbleDp, 0);
ConvertPointToTarget(GetAnchorView()->GetWidget()->GetRootView() /*source*/,
parent() /*target*/, &result);
return result;
}
};
// Focuses the first or last focusable child of |root|. If |reverse| is false,
// this focuses the first focusable child. If |reverse| is true, this focuses
// the last focusable child.
......@@ -455,7 +493,7 @@ LockContentsView::LockContentsView(
warning_banner_bubble_->SetPersistent(true);
AddChildView(warning_banner_bubble_);
auth_error_bubble_ = new LoginErrorBubble();
auth_error_bubble_ = new AuthErrorBubble();
AddChildView(auth_error_bubble_);
OnLockScreenNoteStateChanged(initial_note_action_state);
......
......@@ -6,11 +6,21 @@
#include "ash/login/ui/views_utils.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
namespace ash {
namespace {
// Horizontal and vertical padding of login tooltip view.
constexpr int kHorizontalPaddingLoginTooltipViewDp = 8;
constexpr int kVerticalPaddingLoginTooltipViewDp = 8;
} // namespace
LoginTooltipView::LoginTooltipView(const base::string16& message,
views::View* anchor_view)
: LoginBaseBubbleView(anchor_view) {
......@@ -41,4 +51,32 @@ gfx::Size LoginTooltipView::CalculatePreferredSize() const {
return size;
}
gfx::Point LoginTooltipView::CalculatePosition() {
if (!GetAnchorView())
return gfx::Point();
gfx::Point anchor_position = GetAnchorView()->bounds().origin();
ConvertPointToTarget(GetAnchorView()->parent() /*source*/,
GetAnchorView()->GetWidget()->GetRootView() /*target*/,
&anchor_position);
auto bounds = GetAnchorView()->GetWidget()->GetRootView()->GetLocalBounds();
const int work_area_height =
display::Screen::GetScreen()
->GetDisplayNearestWindow(
GetAnchorView()->GetWidget()->GetNativeWindow())
.work_area()
.height();
bounds.set_height(std::min(bounds.height(), work_area_height));
gfx::Size bubble_size(width() + 2 * kHorizontalPaddingLoginTooltipViewDp,
height() + kVerticalPaddingLoginTooltipViewDp);
auto result = login_views_utils::CalculateBubblePositionLeftRightStrategy(
{anchor_position, GetAnchorView()->size()}, bubble_size, bounds);
// Get position of the bubble surrounded by paddings.
result.Offset(kHorizontalPaddingLoginTooltipViewDp, 0);
ConvertPointToTarget(GetAnchorView()->GetWidget()->GetRootView() /*source*/,
parent() /*target*/, &result);
return result;
}
} // namespace ash
......@@ -20,6 +20,7 @@ class LoginTooltipView : public LoginBaseBubbleView {
// LoginBaseBubbleView:
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
gfx::Point CalculatePosition() override;
// views::View:
gfx::Size CalculatePreferredSize() const override;
......
......@@ -133,5 +133,33 @@ views::View* GetBubbleContainer(views::View* view) {
return container;
}
gfx::Point CalculateBubblePositionLeftRightStrategy(gfx::Rect anchor,
gfx::Size bubble,
gfx::Rect bounds) {
gfx::Rect result(anchor.x() - bubble.width(), anchor.y(), bubble.width(),
bubble.height());
// Trying to show on the left side.
// If there is not enough space show on the right side.
if (result.x() < bounds.x()) {
result.Offset(anchor.width() + result.width(), 0);
}
result.AdjustToFit(bounds);
return result.origin();
}
gfx::Point CalculateBubblePositionRigthLeftStrategy(gfx::Rect anchor,
gfx::Size bubble,
gfx::Rect bounds) {
gfx::Rect result(anchor.x() + anchor.width(), anchor.y(), bubble.width(),
bubble.height());
// Trying to show on the right side.
// If there is not enough space show on the left side.
if (result.right() > bounds.right()) {
result.Offset(-anchor.width() - result.width(), 0);
}
result.AdjustToFit(bounds);
return result.origin();
}
} // namespace login_views_utils
} // namespace ash
......@@ -34,6 +34,16 @@ views::Label* CreateBubbleLabel(const base::string16& message, SkColor color);
// Get the bubble container for |view| to place a LoginBaseBubbleView.
views::View* GetBubbleContainer(views::View* view);
ASH_EXPORT gfx::Point CalculateBubblePositionLeftRightStrategy(
gfx::Rect anchor,
gfx::Size bubble,
gfx::Rect bounds);
ASH_EXPORT gfx::Point CalculateBubblePositionRigthLeftStrategy(
gfx::Rect anchor,
gfx::Size bubble,
gfx::Rect bounds);
} // namespace login_views_utils
} // namespace ash
......
// 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 "ash/login/ui/views_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace ash {
namespace login_views_utils {
namespace {
class ViewsUtilsUnittest : public testing::Test {
protected:
ViewsUtilsUnittest() = default;
~ViewsUtilsUnittest() override = default;
private:
DISALLOW_COPY_AND_ASSIGN(ViewsUtilsUnittest);
};
} // namespace
TEST_F(ViewsUtilsUnittest, LeftRightStrategySimpleTest) {
const gfx::Rect anchor(10, 10, 10, 10);
const gfx::Size bubble(5, 5);
const gfx::Rect bounds(20, 20);
const gfx::Point result_point(anchor.x() - bubble.width(), anchor.y());
EXPECT_EQ(result_point,
CalculateBubblePositionLeftRightStrategy(anchor, bubble, bounds));
}
TEST_F(ViewsUtilsUnittest, LeftRightStrategyNotEnoughHeightBottom) {
const gfx::Rect anchor(10, 10, 10, 10);
const gfx::Size bubble(5, 15);
const gfx::Rect bounds(20, 20);
const gfx::Point result_point(anchor.x() - bubble.width(),
bounds.height() - bubble.height());
EXPECT_EQ(result_point,
CalculateBubblePositionLeftRightStrategy(anchor, bubble, bounds));
}
TEST_F(ViewsUtilsUnittest, LeftRightStrategyNotEnoughHeightBottomAndTop) {
const gfx::Rect anchor(10, 10, 10, 10);
const gfx::Size bubble(5, 25);
const gfx::Rect bounds(20, 20);
const gfx::Point result_point(anchor.x() - bubble.width(), bounds.y());
EXPECT_EQ(result_point,
CalculateBubblePositionLeftRightStrategy(anchor, bubble, bounds));
}
TEST_F(ViewsUtilsUnittest, LeftRightStrategyNotEnoughWidthLeft) {
const gfx::Rect anchor(2, 10, 10, 10);
const gfx::Size bubble(5, 5);
const gfx::Rect bounds(20, 20);
const gfx::Point result_point(anchor.x() + anchor.width(), anchor.y());
EXPECT_EQ(result_point,
CalculateBubblePositionLeftRightStrategy(anchor, bubble, bounds));
}
TEST_F(ViewsUtilsUnittest, RightLeftStrategySimpleTest) {
const gfx::Rect anchor(0, 10, 10, 10);
const gfx::Size bubble(5, 5);
const gfx::Rect bounds(20, 20);
const gfx::Point result_point(anchor.x() + anchor.width(), anchor.y());
EXPECT_EQ(result_point,
CalculateBubblePositionRigthLeftStrategy(anchor, bubble, bounds));
}
TEST_F(ViewsUtilsUnittest, RightLeftStrategyNotEnoughHeightBottom) {
const gfx::Rect anchor(0, 10, 10, 10);
const gfx::Size bubble(5, 15);
const gfx::Rect bounds(20, 20);
const gfx::Point result_point(anchor.x() + anchor.width(),
bounds.height() - bubble.height());
EXPECT_EQ(result_point,
CalculateBubblePositionRigthLeftStrategy(anchor, bubble, bounds));
}
TEST_F(ViewsUtilsUnittest, RightLeftStrategyNotEnoughHeightBottomAndTop) {
const gfx::Rect anchor(0, 10, 10, 10);
const gfx::Size bubble(5, 25);
const gfx::Rect bounds(20, 20);
const gfx::Point result_point(anchor.x() + anchor.width(), bounds.y());
EXPECT_EQ(result_point,
CalculateBubblePositionRigthLeftStrategy(anchor, bubble, bounds));
}
TEST_F(ViewsUtilsUnittest, RightLeftStrategyNotEnoughWidthRight) {
const gfx::Rect anchor(10, 10, 10, 10);
const gfx::Size bubble(5, 5);
const gfx::Rect bounds(20, 20);
const gfx::Point result_point(anchor.x() - bubble.width(), anchor.y());
EXPECT_EQ(result_point,
CalculateBubblePositionRigthLeftStrategy(anchor, bubble, bounds));
}
} // namespace login_views_utils
} // namespace ash
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment