Commit c4f038aa authored by Jacob Dufault's avatar Jacob Dufault Committed by Commit Bot

cros: Better scrollbar behavior on login when scrolling users list

- scrollbar fades in and out
- scrollbar now only appears when scrolling
- scrollbar disappears after a short while if the list was not scrolled

Bug: 859228
Change-Id: I5478f387bd733ded02c476d2de05881df6b8d9ea
Reviewed-on: https://chromium-review.googlesource.com/1185800Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Jacob Dufault <jdufault@chromium.org>
Cr-Commit-Position: refs/heads/master@{#585539}
parent 88aecf78
......@@ -39,6 +39,7 @@ namespace {
namespace ButtonId {
enum {
kGlobalAddUser = 1,
kGlobalAddTenUsers,
kGlobalRemoveUser,
kGlobalToggleBlur,
kGlobalToggleNoteAction,
......@@ -667,6 +668,8 @@ LockDebugView::LockDebugView(mojom::TrayActionState initial_note_action_state,
auto* change_users_container = add_horizontal_container();
AddButton("Add user", ButtonId::kGlobalAddUser, change_users_container);
AddButton("Add 10 users", ButtonId::kGlobalAddTenUsers,
change_users_container);
AddButton("Remove user", ButtonId::kGlobalRemoveUser, change_users_container);
auto* toggle_container = add_horizontal_container();
......@@ -773,11 +776,14 @@ void LockDebugView::ButtonPressed(views::Button* sender,
const ui::Event& event) {
// Add or remove a user.
bool is_add_user = sender->id() == ButtonId::kGlobalAddUser;
bool is_add_many_users = sender->id() == ButtonId::kGlobalAddTenUsers;
bool is_remove_user = sender->id() == ButtonId::kGlobalRemoveUser;
if (is_add_user || is_remove_user) {
if (is_add_user || is_add_many_users || is_remove_user) {
int num_users = debug_data_dispatcher_->GetUserCount();
if (is_add_user)
++num_users;
else if (is_add_many_users)
num_users += 10;
else if (is_remove_user)
--num_users;
if (num_users < 0)
......
......@@ -4,7 +4,8 @@
#include "ash/login/ui/scrollable_users_list_view.h"
#include "ash/login/ui/hover_notifier.h"
#include <limits>
#include "ash/login/ui/login_display_style.h"
#include "ash/login/ui/login_user_view.h"
#include "ash/login/ui/non_accessible_view.h"
......@@ -13,6 +14,8 @@
#include "ash/public/interfaces/login_user_info.mojom.h"
#include "ash/shell.h"
#include "ash/wallpaper/wallpaper_controller.h"
#include "base/numerics/ranges.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/display/screen.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_analysis.h"
......@@ -52,6 +55,12 @@ constexpr int kScrollThumbPaddingDp = 8;
constexpr int kScrollThumbRadiusDp = 8;
// Alpha of scroll bar thumb (43/255 = 17%).
constexpr int kScrollThumbAlpha = 43;
// How long for the scrollbar to hide after no scroll events have been received?
constexpr base::TimeDelta kScrollThumbHideTimeout =
base::TimeDelta::FromMilliseconds(500);
// How long for the scrollbar to fade away?
constexpr base::TimeDelta kScrollThumbFadeDuration =
base::TimeDelta::FromMilliseconds(240);
constexpr char kScrollableUsersListContentViewName[] =
"ScrollableUsersListContent";
......@@ -141,16 +150,24 @@ LayoutParams BuildLayoutForStyle(LoginDisplayStyle style) {
}
}
} // namespace
class ScrollableUsersListView::ScrollBar : public views::BaseScrollBar {
// Shows a scrollbar that automatically displays and hides itself when content
// is scrolled.
class UsersListScrollBar : public views::BaseScrollBar {
public:
explicit ScrollBar(bool horizontal) : BaseScrollBar(horizontal) {
explicit UsersListScrollBar(bool horizontal)
: BaseScrollBar(horizontal),
hide_scrollbar_timer_(
FROM_HERE,
kScrollThumbHideTimeout,
base::BindRepeating(&UsersListScrollBar::HideScrollBar,
base::Unretained(this))) {
SetThumb(new ScrollBarThumb(this));
GetThumb()->SetPaintToLayer();
GetThumb()->layer()->SetFillsBoundsOpaquely(false);
// The thumb is hidden by default.
GetThumb()->layer()->SetOpacity(0);
}
~ScrollBar() override = default;
void SetThumbVisible(bool visible) { GetThumb()->SetVisible(visible); }
~UsersListScrollBar() override = default;
// views::BaseScrollBar:
gfx::Rect GetTrackBounds() const override { return GetLocalBounds(); }
......@@ -158,11 +175,68 @@ class ScrollableUsersListView::ScrollBar : public views::BaseScrollBar {
int GetThickness() const override {
return kScrollThumbThicknessDp + kScrollThumbPaddingDp;
}
void OnMouseEntered(const ui::MouseEvent& event) override {
mouse_over_scrollbar_ = true;
ShowScrollbar();
}
void OnMouseExited(const ui::MouseEvent& event) override {
mouse_over_scrollbar_ = false;
if (!hide_scrollbar_timer_.IsRunning())
hide_scrollbar_timer_.Reset();
}
void ScrollToPosition(int position) override {
ShowScrollbar();
views::BaseScrollBar::ScrollToPosition(position);
}
void ObserveScrollEvent(const ui::ScrollEvent& event) override {
// Scroll fling events are generated by moving a single finger over the
// trackpad; do not show the scrollbar for these events.
if (event.type() == ui::ET_SCROLL_FLING_CANCEL)
return;
ShowScrollbar();
}
private:
DISALLOW_COPY_AND_ASSIGN(ScrollBar);
void ShowScrollbar() {
bool currently_hidden =
base::IsApproximatelyEqual(GetThumb()->layer()->GetTargetOpacity(), 0.f,
std::numeric_limits<float>::epsilon());
if (!mouse_over_scrollbar_)
hide_scrollbar_timer_.Reset();
if (currently_hidden) {
ui::ScopedLayerAnimationSettings animation(
GetThumb()->layer()->GetAnimator());
animation.SetTransitionDuration(kScrollThumbFadeDuration);
GetThumb()->layer()->SetOpacity(1);
}
}
void HideScrollBar() {
// Never hide the scrollbar if the mouse is over it. The auto-hide timer
// will be reset when the mouse leaves the scrollable area.
if (mouse_over_scrollbar_)
return;
hide_scrollbar_timer_.Stop();
ui::ScopedLayerAnimationSettings animation(
GetThumb()->layer()->GetAnimator());
animation.SetTransitionDuration(kScrollThumbFadeDuration);
GetThumb()->layer()->SetOpacity(0);
}
// When the mouse is hovering over the scrollbar, the scrollbar should always
// be displayed.
bool mouse_over_scrollbar_ = false;
// Timer that will start the scrollbar's hiding animation when it reaches 0.
base::RetainingOneShotTimer hide_scrollbar_timer_;
DISALLOW_COPY_AND_ASSIGN(UsersListScrollBar);
};
} // namespace
// static
ScrollableUsersListView::GradientParams
ScrollableUsersListView::GradientParams::BuildForStyle(
......@@ -258,13 +332,8 @@ ScrollableUsersListView::ScrollableUsersListView(
SetBackgroundColor(SK_ColorTRANSPARENT);
set_draw_overflow_indicator(false);
vertical_scroll_bar_ = new ScrollBar(false);
SetVerticalScrollBar(vertical_scroll_bar_);
SetHorizontalScrollBar(new ScrollBar(true));
hover_notifier_ = std::make_unique<HoverNotifier>(
this, base::BindRepeating(&ScrollableUsersListView::OnHover,
base::Unretained(this)));
SetVerticalScrollBar(new UsersListScrollBar(false));
SetHorizontalScrollBar(new UsersListScrollBar(true));
observer_.Add(Shell::Get()->wallpaper_controller());
}
......@@ -301,10 +370,6 @@ void ScrollableUsersListView::Layout() {
// Layout everything.
ScrollView::Layout();
// Update scrollbar visibility.
if (vertical_scroll_bar_)
vertical_scroll_bar_->SetThumbVisible(IsMouseHovered());
}
void ScrollableUsersListView::OnPaintBackground(gfx::Canvas* canvas) {
......@@ -324,7 +389,7 @@ void ScrollableUsersListView::OnPaintBackground(gfx::Canvas* canvas) {
cc::PaintFlags flags;
// Only draw a gradient if the content can be scrolled.
if (vertical_scroll_bar_->visible()) {
if (vertical_scroll_bar()->visible()) {
// Draws symmetrical linear gradient at the top and bottom of the view.
SkScalar view_height = render_bounds.height();
SkScalar gradient_height = gradient_params_.height;
......@@ -377,8 +442,4 @@ void ScrollableUsersListView::OnWallpaperBlurChanged() {
SchedulePaint();
}
void ScrollableUsersListView::OnHover(bool has_hover) {
vertical_scroll_bar_->SetThumbVisible(has_hover);
}
} // namespace ash
......@@ -23,7 +23,6 @@ class BoxLayout;
namespace ash {
class HoverNotifier;
class WallpaperController;
// Scrollable list of the users. Stores the list of login user views. Can be
......@@ -75,8 +74,6 @@ class ASH_EXPORT ScrollableUsersListView : public views::ScrollView,
void OnWallpaperBlurChanged() override;
private:
class ScrollBar;
struct GradientParams {
static GradientParams BuildForStyle(LoginDisplayStyle style);
......@@ -88,9 +85,6 @@ class ASH_EXPORT ScrollableUsersListView : public views::ScrollView,
SkScalar height = 0;
};
// Updates visibility of scroll bar thumb. Called when hover state changes.
void OnHover(bool has_hover);
// Display style to determine layout and sizing of users list.
const LoginDisplayStyle display_style_;
......@@ -100,13 +94,8 @@ class ASH_EXPORT ScrollableUsersListView : public views::ScrollView,
// Layout for |user_view_host_|.
views::BoxLayout* user_view_host_layout_ = nullptr;
// Owned by ScrollView.
ScrollBar* vertical_scroll_bar_ = nullptr;
std::vector<LoginUserView*> user_views_;
std::unique_ptr<HoverNotifier> hover_notifier_;
GradientParams gradient_params_;
ScopedObserver<WallpaperController, WallpaperControllerObserver> observer_{
......
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