Commit 45b1c565 authored by minch's avatar minch Committed by Chromium LUCI CQ

bento: Zero state of desks

See demo at the crbug.

Bug: 1158583
Change-Id: I7ee3ff75c2126543a2fe215817281c11540d080a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2604683Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Commit-Queue: Min Chen <minch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843211}
parent c97db3d4
......@@ -1516,10 +1516,14 @@ component("ash") {
"wm/desks/desks_restore_util.cc",
"wm/desks/desks_restore_util.h",
"wm/desks/desks_util.cc",
"wm/desks/expanded_state_new_desk_button.cc",
"wm/desks/expanded_state_new_desk_button.h",
"wm/desks/new_desk_button.cc",
"wm/desks/new_desk_button.h",
"wm/desks/root_window_desk_switch_animator.cc",
"wm/desks/root_window_desk_switch_animator.h",
"wm/desks/zero_state_button.cc",
"wm/desks/zero_state_button.h",
"wm/drag_details.cc",
"wm/drag_details.h",
"wm/drag_window_controller.cc",
......
......@@ -6,9 +6,11 @@
#include <utility>
#include "ash/public/cpp/ash_features.h"
#include "ash/shell.h"
#include "ash/wm/desks/desk_mini_view.h"
#include "ash/wm/desks/desks_bar_view.h"
#include "ash/wm/desks/expanded_state_new_desk_button.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/overview/overview_session.h"
#include "ui/compositor/layer.h"
......@@ -41,18 +43,22 @@ void InitScopedAnimationSettings(ui::ScopedLayerAnimationSettings* settings,
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
}
// Animates the transforms of the layers of the given |mini_views| from the
// supplied |begin_transform| to the identity transform.
void AnimateMiniViews(std::vector<DeskMiniView*> mini_views,
const gfx::Transform& begin_transform) {
for (auto* mini_view : mini_views) {
ui::Layer* layer = mini_view->layer();
// Animates the transform of the layer of the given |view| from the supplied
// |begin_transform| to the identity transform.
void AnimateView(views::View* view, const gfx::Transform& begin_transform) {
ui::Layer* layer = view->layer();
layer->SetTransform(begin_transform);
ui::ScopedLayerAnimationSettings settings{layer->GetAnimator()};
InitScopedAnimationSettings(&settings, kExistingMiniViewsAnimationDuration);
layer->SetTransform(kEndTransform);
}
}
// See details at AnimateView.
void AnimateMiniViews(std::vector<DeskMiniView*> mini_views,
const gfx::Transform& begin_transform) {
for (auto* mini_view : mini_views)
AnimateView(mini_view, begin_transform);
}
// A self-deleting object that performs a fade out animation on
......@@ -129,12 +135,25 @@ void PerformNewDeskMiniViewAnimation(
layer->SetOpacity(1);
layer->SetTransform(kEndTransform);
}
// The new desk button in the expanded desks bar moves at the opposite
// direction of the existing mini views while creating a new mini view. The
// existing mini views will move from right to left while the new desk button
// will move from left to right. Since the newly added mini view will be added
// between the last mini view and the new desk button.
if (features::IsBentoEnabled()) {
gfx::Transform new_desk_button_begin_transform;
new_desk_button_begin_transform.Translate(-shift_x, 0);
AnimateView(bar_view->expanded_state_new_desk_button(),
new_desk_button_begin_transform);
}
}
void PerformRemoveDeskMiniViewAnimation(
DeskMiniView* removed_mini_view,
std::vector<DeskMiniView*> mini_views_left,
std::vector<DeskMiniView*> mini_views_right,
ExpandedStateNewDeskButton* expanded_state_new_desk_button,
int shift_x) {
gfx::Transform mini_views_left_begin_transform;
mini_views_left_begin_transform.Translate(shift_x, 0);
......@@ -145,6 +164,11 @@ void PerformRemoveDeskMiniViewAnimation(
AnimateMiniViews(mini_views_left, mini_views_left_begin_transform);
AnimateMiniViews(mini_views_right, mini_views_right_begin_transform);
if (features::IsBentoEnabled()) {
AnimateView(expanded_state_new_desk_button,
mini_views_right_begin_transform);
}
}
} // namespace ash
......@@ -12,6 +12,7 @@ namespace ash {
class DesksBarView;
class DeskMiniView;
class ExpandedStateNewDeskButton;
// Animates new desk mini_views, fading them in and moving them from right to
// left into their final positions in the desk bar view. It will also animate
......@@ -39,15 +40,18 @@ void PerformNewDeskMiniViewAnimation(
// |removed_mini_view| from the views hierarchy and deleting it.
// |mini_views_left|, and |mini_views_right| are lists of the remaining
// mini_views to left and to the right of the removed mini_view respectively.
// Either list can be empty (e.g. if the removed mini_view is the last one on
// the right). |shift_x| is the amount by which the remaining mini_views will be
// moved horizontally to occupy the space that the removed mini_view used to
// occupy. It assumes that the remiaing mini_views have been laid out in their
// final positions as if the removed mini_view no longer exits.
// |expanded_state_new_desk_button| will be moved to right the same as
// |mini_views_right| if Bento is enabled. Either list can be empty (e.g. if the
// removed mini_view is the last one on the right). |shift_x| is the amount by
// which the remaining mini_views will be moved horizontally to occupy the space
// that the removed mini_view used to occupy. It assumes that the remaining
// mini_views have been laid out in their final positions as if the removed
// mini_view no longer exists.
void PerformRemoveDeskMiniViewAnimation(
DeskMiniView* removed_mini_view,
std::vector<DeskMiniView*> mini_views_left,
std::vector<DeskMiniView*> mini_views_right,
ExpandedStateNewDeskButton* expanded_state_new_desk_button,
int shift_x);
} // namespace ash
......
......@@ -26,7 +26,6 @@
#include "ui/compositor/layer_type.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rounded_corners_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/gfx/skia_paint_util.h"
......
This diff is collapsed.
......@@ -15,10 +15,13 @@
namespace ash {
class DeskBarHoverObserver;
class DeskMiniView;
class ExpandedStateNewDeskButton;
class NewDeskButton;
class DeskBarHoverObserver;
class OverviewGrid;
class ZeroStateDefaultDeskButton;
class ZeroStateNewDeskButton;
// A bar that resides at the top portion of the overview mode's ShieldView,
// which contains the virtual desks mini_views, as well as the new desk button.
......@@ -28,6 +31,8 @@ class ASH_EXPORT DesksBarView : public views::View,
explicit DesksBarView(OverviewGrid* overview_grid);
~DesksBarView() override;
static constexpr int kZeroStateBarHeight = 40;
// Returns the height of the desk bar view which is based on the given |width|
// of the overview grid that exists on |root| (which is the same as the width
// of the bar) and |desks_bar_view|'s content (since they may not fit the
......@@ -49,6 +54,18 @@ class ASH_EXPORT DesksBarView : public views::View,
NewDeskButton* new_desk_button() const { return new_desk_button_; }
ZeroStateDefaultDeskButton* zero_state_default_desk_button() const {
return zero_state_default_desk_button_;
}
ZeroStateNewDeskButton* zero_state_new_desk_button() const {
return zero_state_new_desk_button_;
}
ExpandedStateNewDeskButton* expanded_state_new_desk_button() const {
return expanded_state_new_desk_button_;
}
const std::vector<DeskMiniView*>& mini_views() const { return mini_views_; }
const gfx::Point& last_dragged_item_screen_location() const {
......@@ -82,6 +99,11 @@ class ASH_EXPORT DesksBarView : public views::View,
void SetDragDetails(const gfx::Point& screen_location,
bool dragged_item_over_bar);
// Returns true if it is in zero state. It is the state of the desks bar when
// there's only a single desk available, in which case the bar is shown in a
// minimized state.
bool IsZeroState() const;
// views::View:
const char* GetClassName() const override;
bool OnMousePressed(const ui::MouseEvent& event) override;
......@@ -102,12 +124,15 @@ class ASH_EXPORT DesksBarView : public views::View,
void OnDeskSwitchAnimationLaunching() override;
void OnDeskSwitchAnimationFinished() override;
private:
// This is called on initialization or when a new desk is created to create
// the needed new mini_views. If |initializing_bar_view| is false, the
// mini_views will be animated to their final positions.
void UpdateNewMiniViews(bool initializing_bar_view);
// This is called on initialization, creating a new desk through the
// NewDeskButton or ExpandedStateNewDeskButton, or expanding from zero state
// bar to the expanded desks bar when Bento is enabled. Performs the expanding
// animation if |expanding_bar_view| is true, otherwise animates the
// mini_views (also the ExpandedStateNewDeskButton if Bento is enabled) to
// their final positions if |initializing_bar_view| is false.
void UpdateNewMiniViews(bool initializing_bar_view, bool expanding_bar_view);
private:
// Returns the mini_view associated with |desk| or nullptr if no mini_view
// has been created for it yet.
DeskMiniView* FindMiniViewForDesk(const Desk* desk) const;
......@@ -125,10 +150,20 @@ class ASH_EXPORT DesksBarView : public views::View,
// child if Bento is enabled.
DeskMiniView* AddMiniViewAsChild(std::unique_ptr<DeskMiniView> mini_view);
// Updates the visibility of the two buttons inside the zero state desks bar
// and the ExpandedStateNewDeskButton on the desk bar's state. Used only when
// Bento is enabled.
void UpdateBentoDeskButtonsVisibility();
// Translates the background view and positions windows in overview while
// switching between zero state desks bar and expanded desks bar.
void SetExpanded(bool expanded);
// A view that shows a dark gary transparent background that can be animated
// when the very first mini_views are created.
views::View* background_view_;
// Used only in classic desks. Will be removed once Bento is fully launched.
NewDeskButton* new_desk_button_;
// The views representing desks mini_views. They're owned by views hierarchy.
......@@ -160,6 +195,11 @@ class ASH_EXPORT DesksBarView : public views::View,
// |new_desk_button_| currently. Used only when Bento is enabled.
views::View* scroll_view_contents_ = nullptr;
// Used only when Bento is enabled.
ZeroStateDefaultDeskButton* zero_state_default_desk_button_;
ZeroStateNewDeskButton* zero_state_new_desk_button_;
ExpandedStateNewDeskButton* expanded_state_new_desk_button_;
DISALLOW_COPY_AND_ASSIGN(DesksBarView);
};
......
This diff is collapsed.
// Copyright 2021 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/wm/desks/expanded_state_new_desk_button.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h"
#include "ash/wm/desks/desk_preview_view.h"
#include "ash/wm/desks/desks_bar_view.h"
#include "ash/wm/desks/zero_state_button.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/overview/overview_session.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/controls/label.h"
namespace ash {
namespace {
constexpr int kNewDeskButtonAndNameSpacing = 8;
// The new desk button in expand desks bar in Bento has the same size as the
// desk preview, which is proportional to the size of the display on which it
// resides.
gfx::Rect GetExpandedStateNewDeskButtonBounds(aura::Window* root_window) {
const int preview_height =
DeskPreviewView::GetHeight(root_window, /*compact=*/false);
const auto root_size = root_window->bounds().size();
return gfx::Rect(preview_height * root_size.width() / root_size.height(),
preview_height);
}
// The button belongs to ExpandedStateNewDeskButton.
class ASH_EXPORT InnerNewDeskButton : public DeskButtonBase {
public:
InnerNewDeskButton() : DeskButtonBase(base::string16()) {
paint_contents_only_ = true;
}
InnerNewDeskButton(const InnerNewDeskButton&) = delete;
InnerNewDeskButton operator=(const InnerNewDeskButton&) = delete;
~InnerNewDeskButton() override = default;
// DeskButtonBase:
const char* GetClassName() const override { return "InnerNewDeskButton"; }
void OnThemeChanged() override {
DeskButtonBase::OnThemeChanged();
AshColorProvider::Get()->DecoratePillButton(this, &kDesksNewDeskButtonIcon);
UpdateButtonState();
}
void OnButtonPressed() override {
auto* controller = DesksController::Get();
if (controller->CanCreateDesks()) {
controller->NewDesk(DesksCreationRemovalSource::kButton);
UpdateButtonState();
}
}
// Update the button's enable/disable state based on current desks state.
void UpdateButtonState() override {
const bool enabled = DesksController::Get()->CanCreateDesks();
// Notify the overview highlight if we are about to be disabled.
if (!enabled) {
OverviewSession* overview_session =
Shell::Get()->overview_controller()->overview_session();
DCHECK(overview_session);
overview_session->highlight_controller()->OnViewDestroyingOrDisabling(
this);
}
SetEnabled(enabled);
const auto* color_provider = AshColorProvider::Get();
background_color_ = color_provider->GetControlsLayerColor(
AshColorProvider::ControlsLayerType::kControlBackgroundColorInactive);
if (!enabled)
background_color_ = AshColorProvider::GetDisabledColor(background_color_);
SetInkDropVisibleOpacity(
color_provider->GetRippleAttributes(background_color_).inkdrop_opacity);
SchedulePaint();
}
};
} // namespace
ExpandedStateNewDeskButton::ExpandedStateNewDeskButton(DesksBarView* bar_view)
: bar_view_(bar_view),
new_desk_button_(AddChildView(std::make_unique<InnerNewDeskButton>())),
label_(AddChildView(std::make_unique<views::Label>())) {
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
label_->SetText(l10n_util::GetStringUTF16(IDS_ASH_DESKS_NEW_DESK_BUTTON));
label_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
}
void ExpandedStateNewDeskButton::Layout() {
const gfx::Rect new_desk_button_bounds = GetExpandedStateNewDeskButtonBounds(
bar_view_->GetWidget()->GetNativeWindow()->GetRootWindow());
new_desk_button_->SetBoundsRect(new_desk_button_bounds);
const gfx::Size label_size = label_->GetPreferredSize();
label_->SetBoundsRect(gfx::Rect(
gfx::Point(
(new_desk_button_bounds.width() - label_size.width()) / 2,
new_desk_button_bounds.bottom() + kNewDeskButtonAndNameSpacing),
label_size));
}
void ExpandedStateNewDeskButton::UpdateButtonState() {
new_desk_button_->UpdateButtonState();
}
} // namespace ash
// Copyright 2021 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_WM_DESKS_EXPANDED_STATE_NEW_DESK_BUTTON_H_
#define ASH_WM_DESKS_EXPANDED_STATE_NEW_DESK_BUTTON_H_
#include "ui/views/view.h"
namespace views {
class Label;
} // namespace views
namespace ash {
class DeskButtonBase;
class DesksBarView;
// TODO(minch): Build the base class DeskMiniViewBase, and let both the
// ExpandedStateNewDeskButton and DeskMiniView inherit from it. Then the
// expanded state new desk button can be treated the same as |mini_views_| in
// DesksBarView. It then can share the same animation and layout as other mini
// views.
// The new desk button view in the expanded desks bar in Bento. It includes the
// InnerNewDeskButton and a name label below, which has the same style as a
// DeskMiniVIew. But the name label is not changeable and not focusable.
class ExpandedStateNewDeskButton : public views::View {
public:
ExpandedStateNewDeskButton(DesksBarView* bar_view);
ExpandedStateNewDeskButton(const ExpandedStateNewDeskButton&) = delete;
ExpandedStateNewDeskButton& operator=(const ExpandedStateNewDeskButton&) =
delete;
~ExpandedStateNewDeskButton() override = default;
// views::View:
void Layout() override;
// Updates |new_desk_button_|'s state on current desks state.
void UpdateButtonState();
DeskButtonBase* new_desk_button() { return new_desk_button_; }
private:
DesksBarView* bar_view_; // Not owned.
DeskButtonBase* new_desk_button_;
views::Label* label_;
};
} // namespace ash
#endif // ASH_WM_DESKS_EXPANDED_STATE_NEW_DESK_BUTTON_H_
......@@ -23,7 +23,6 @@
#include "ui/gfx/canvas.h"
#include "ui/views/animation/ink_drop_impl.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/label_button_border.h"
#include "ui/views/controls/highlight_path_generator.h"
......@@ -159,13 +158,6 @@ SkColor NewDeskButton::GetInkDropBaseColor() const {
.base_color;
}
std::unique_ptr<views::LabelButtonBorder> NewDeskButton::CreateDefaultBorder()
const {
std::unique_ptr<views::LabelButtonBorder> border =
std::make_unique<views::LabelButtonBorder>();
return border;
}
void NewDeskButton::OnThemeChanged() {
LabelButton::OnThemeChanged();
AshColorProvider::Get()->DecoratePillButton(this, &kDesksNewDeskButtonIcon);
......
......@@ -16,6 +16,8 @@ namespace ash {
class WmHighlightItemBorder;
// TODO(minch): Remove NewDeskButton once Bento feature is fully launched. Since
// ExpandedStateNewDeskButton will be used instead.
// A button view that shows up in the top-right corner of the screen when
// overview mode is on, which is used to create a new virtual desk.
class ASH_EXPORT NewDeskButton
......@@ -49,8 +51,6 @@ class ASH_EXPORT NewDeskButton
std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
const override;
SkColor GetInkDropBaseColor() const override;
std::unique_ptr<views::LabelButtonBorder> CreateDefaultBorder()
const override;
void OnThemeChanged() override;
// OverviewHighlightController::OverviewHighlightableView:
......
// Copyright 2021 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/wm/desks/zero_state_button.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h"
#include "ash/wm/desks/desks_bar_view.h"
#include "ash/wm/desks/desks_controller.h"
#include "ash/wm/wm_highlight_item_border.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/canvas.h"
#include "ui/views/animation/ink_drop_impl.h"
#include "ui/views/controls/highlight_path_generator.h"
namespace ash {
namespace {
constexpr int kCornerRadius = 8;
constexpr int kZeroStateButtonHeight = 28;
constexpr int kZeroStateDefaultButtonHorizontalPadding = 16;
constexpr int kZeroStateNewDeskButtonWidth = 36;
} // namespace
// -----------------------------------------------------------------------------
// DeskButtonBase:
DeskButtonBase::DeskButtonBase(const base::string16& text)
: LabelButton(base::BindRepeating(&DeskButtonBase::OnButtonPressed,
base::Unretained(this)),
text) {
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
SetHorizontalAlignment(gfx::ALIGN_CENTER);
SetInkDropMode(InkDropMode::ON);
SetHasInkDropActionOnClick(true);
SetFocusPainter(nullptr);
SetFocusBehavior(views::View::FocusBehavior::ACCESSIBLE_ONLY);
auto border = std::make_unique<WmHighlightItemBorder>(kCornerRadius);
border_ptr_ = border.get();
SetBorder(std::move(border));
views::InstallRoundRectHighlightPathGenerator(this, GetInsets(),
kCornerRadius);
UpdateBorderState();
}
const char* DeskButtonBase::GetClassName() const {
return "DeskButtonBase";
}
void DeskButtonBase::OnPaintBackground(gfx::Canvas* canvas) {
if (highlight_on_hover_) {
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(background_color_);
canvas->DrawRoundRect(gfx::RectF(paint_contents_only_ ? GetContentsBounds()
: GetLocalBounds()),
kCornerRadius, flags);
}
}
std::unique_ptr<views::InkDrop> DeskButtonBase::CreateInkDrop() {
auto ink_drop = CreateDefaultFloodFillInkDropImpl();
// Do not show highlight on hover and focus. Since the button will be painted
// with a background, see |highlight_on_hover_| for more details.
ink_drop->SetShowHighlightOnHover(false);
ink_drop->SetShowHighlightOnFocus(false);
return std::move(ink_drop);
}
std::unique_ptr<views::InkDropHighlight>
DeskButtonBase::CreateInkDropHighlight() const {
auto highlight = std::make_unique<views::InkDropHighlight>(
gfx::SizeF(size()), GetInkDropBaseColor());
highlight->set_visible_opacity(AshColorProvider::Get()
->GetRippleAttributes(background_color_)
.highlight_opacity);
return highlight;
}
SkColor DeskButtonBase::GetInkDropBaseColor() const {
return AshColorProvider::Get()
->GetRippleAttributes(background_color_)
.base_color;
}
void DeskButtonBase::OnThemeChanged() {
LabelButton::OnThemeChanged();
background_color_ = AshColorProvider::Get()->GetControlsLayerColor(
AshColorProvider::ControlsLayerType::kControlBackgroundColorInactive);
SchedulePaint();
}
views::View* DeskButtonBase::GetView() {
return this;
}
void DeskButtonBase::MaybeActivateHighlightedView() {
OnButtonPressed();
}
void DeskButtonBase::MaybeCloseHighlightedView() {}
void DeskButtonBase::OnViewHighlighted() {
UpdateBorderState();
}
void DeskButtonBase::OnViewUnhighlighted() {
UpdateBorderState();
}
void DeskButtonBase::UpdateBorderState() {
border_ptr_->SetFocused(IsViewHighlighted() &&
DesksController::Get()->CanCreateDesks());
SchedulePaint();
}
// -----------------------------------------------------------------------------
// ZeroStateDefaultDeskButton:
// TODO(minch): Show the first desk's current name instead of the default name.
ZeroStateDefaultDeskButton::ZeroStateDefaultDeskButton(DesksBarView* bar_view)
: DeskButtonBase(
l10n_util::GetStringUTF16(IDS_ASH_DESKS_DESK_1_MINI_VIEW_TITLE)),
bar_view_(bar_view) {}
const char* ZeroStateDefaultDeskButton::GetClassName() const {
return "ZeroStateDefaultDeskButton";
}
void ZeroStateDefaultDeskButton::OnThemeChanged() {
DeskButtonBase::OnThemeChanged();
SetEnabledTextColors(AshColorProvider::Get()->GetContentLayerColor(
AshColorProvider::ContentLayerType::kTextColorPrimary));
}
gfx::Size ZeroStateDefaultDeskButton::CalculatePreferredSize() const {
const gfx::Size label_size = label()->GetPreferredSize();
return gfx::Size(
label_size.width() + 2 * kZeroStateDefaultButtonHorizontalPadding,
kZeroStateButtonHeight);
}
void ZeroStateDefaultDeskButton::OnButtonPressed() {
bar_view_->UpdateNewMiniViews(/*initializing_bar_view=*/false,
/*expanding_bar_view=*/true);
}
// -----------------------------------------------------------------------------
// ZeroStateNewDeskButton:
ZeroStateNewDeskButton::ZeroStateNewDeskButton()
: DeskButtonBase(base::string16()) {
highlight_on_hover_ = false;
}
const char* ZeroStateNewDeskButton::GetClassName() const {
return "ZeroStateNewDeskButton";
}
void ZeroStateNewDeskButton::OnThemeChanged() {
DeskButtonBase::OnThemeChanged();
AshColorProvider::Get()->DecoratePillButton(this, &kDesksNewDeskButtonIcon);
}
gfx::Size ZeroStateNewDeskButton::CalculatePreferredSize() const {
return gfx::Size(kZeroStateNewDeskButtonWidth, kZeroStateButtonHeight);
}
void ZeroStateNewDeskButton::OnButtonPressed() {
DesksController::Get()->NewDesk(DesksCreationRemovalSource::kButton);
highlight_on_hover_ = false;
}
void ZeroStateNewDeskButton::OnMouseEntered(const ui::MouseEvent& event) {
highlight_on_hover_ = true;
SchedulePaint();
}
void ZeroStateNewDeskButton::OnMouseExited(const ui::MouseEvent& event) {
highlight_on_hover_ = false;
SchedulePaint();
}
} // namespace ash
// Copyright 2021 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_WM_DESKS_ZERO_STATE_BUTTON_H_
#define ASH_WM_DESKS_ZERO_STATE_BUTTON_H_
#include "ash/ash_export.h"
#include "ash/wm/overview/overview_highlight_controller.h"
#include "ui/views/controls/button/label_button.h"
namespace ash {
class DesksBarView;
class WmHighlightItemBorder;
// The base class of ZeroStateDefaultDeskButton, ZeroStateNewDeskButton and
// the InnerNewDeskButton of ExpandedStateNewDeskButton.
class ASH_EXPORT DeskButtonBase
: public views::LabelButton,
public OverviewHighlightController::OverviewHighlightableView {
public:
explicit DeskButtonBase(const base::string16& text);
~DeskButtonBase() override = default;
// LabelButton:
const char* GetClassName() const override;
void OnPaintBackground(gfx::Canvas* canvas) override;
std::unique_ptr<views::InkDrop> CreateInkDrop() override;
std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
const override;
SkColor GetInkDropBaseColor() const override;
void OnThemeChanged() override;
// OverviewHighlightController::OverviewHighlightableView:
views::View* GetView() override;
void MaybeActivateHighlightedView() override;
void MaybeCloseHighlightedView() override;
void OnViewHighlighted() override;
void OnViewUnhighlighted() override;
virtual void UpdateButtonState() {}
protected:
virtual void OnButtonPressed() = 0;
SkColor background_color_;
// If true, paints the button with the background of |background_color_|. The
// button is painted with the background by default, exception like
// ZeroStateNewDeskButton only wants to be painted when the mouse hovers.
bool highlight_on_hover_ = true;
// Paints the background within the button's bounds by default. But if true,
// paints the contents' bounds of the button only. For example,
// InnerNewDeskButton needs to be kept as the same size of the desk preview,
// which has a gap between the view's contents and the border.
bool paint_contents_only_ = false;
private:
void UpdateBorderState();
// Owned by this View via `View::border_`. This is just a convenient pointer
// to it.
WmHighlightItemBorder* border_ptr_;
};
// A button in zero state bar showing "Desk 1". Zero state is the state of the
// desks bar when there's only a single desk available, in which case the bar is
// shown in a minimized state. Clicking the button will switch to the expanded
// desks bar and focus on the single desk's name view. The expanded bar will
// include the single desk and the ExpandedStateNewDeskButton.
class ASH_EXPORT ZeroStateDefaultDeskButton : public DeskButtonBase {
public:
ZeroStateDefaultDeskButton(DesksBarView* bar_view);
ZeroStateDefaultDeskButton(const ZeroStateDefaultDeskButton&) = delete;
ZeroStateDefaultDeskButton operator=(const ZeroStateDefaultDeskButton&) =
delete;
~ZeroStateDefaultDeskButton() override = default;
// DeskButtonBase:
const char* GetClassName() const override;
void OnThemeChanged() override;
gfx::Size CalculatePreferredSize() const override;
void OnButtonPressed() override;
private:
DesksBarView* bar_view_;
};
// A button in zero state bar with a plus icon. Zero state is the state of the
// desks bar when there's only a single desk available, in which case the bar is
// shown in a minimized state. Clicking the button will create a new desk,
// switch to the expanded desks bar and focus on the newly-created desks's name
// view. The expanded bar will include two desks and the
// ExpandedStateNewDeskButton.
class ASH_EXPORT ZeroStateNewDeskButton : public DeskButtonBase {
public:
ZeroStateNewDeskButton();
ZeroStateNewDeskButton(const ZeroStateNewDeskButton&) = delete;
ZeroStateNewDeskButton operator=(const ZeroStateNewDeskButton&) = delete;
~ZeroStateNewDeskButton() override = default;
// DeskButtonBase:
const char* GetClassName() const override;
void OnThemeChanged() override;
gfx::Size CalculatePreferredSize() const override;
void OnButtonPressed() override;
// views::Button:
void OnMouseEntered(const ui::MouseEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;
};
} // namespace ash
#endif // ASH_WM_DESKS_ZERO_STATE_BUTTON_H_
......@@ -1331,7 +1331,8 @@ bool OverviewGrid::IsDesksBarViewActive() const {
// The desk bar view is not active if there is only a single desk when
// overview is started. Once there are more than one desk, it should stay
// active even if the 2nd to last desk is deleted.
// active even if the 2nd to last desk is deleted in classic desks. Zero state
// desks bar in Bento should not be treated as active.
return DesksController::Get()->desks().size() > 1 ||
(desks_bar_view_ && !desks_bar_view_->mini_views().empty());
}
......
......@@ -6,12 +6,15 @@
#include "ash/magnifier/docked_magnifier_controller_impl.h"
#include "ash/magnifier/magnification_controller.h"
#include "ash/public/cpp/ash_features.h"
#include "ash/shell.h"
#include "ash/wm/desks/desk_mini_view.h"
#include "ash/wm/desks/desk_name_view.h"
#include "ash/wm/desks/desks_bar_view.h"
#include "ash/wm/desks/desks_util.h"
#include "ash/wm/desks/expanded_state_new_desk_button.h"
#include "ash/wm/desks/new_desk_button.h"
#include "ash/wm/desks/zero_state_button.h"
#include "ash/wm/overview/overview_grid.h"
#include "ash/wm/overview/overview_item.h"
#include "ash/wm/overview/overview_item_view.h"
......@@ -205,16 +208,28 @@ OverviewHighlightController::GetTraversableViews() const {
for (auto& grid : overview_session_->grid_list()) {
auto* bar_view = grid->desks_bar_view();
if (bar_view) {
const bool is_zero_state = bar_view->IsZeroState();
// The desk items are always traversable from left to right, even in RTL
// languages.
if (is_zero_state) {
traversable_views.push_back(bar_view->zero_state_default_desk_button());
traversable_views.push_back(bar_view->zero_state_new_desk_button());
} else {
for (auto* mini_view : bar_view->mini_views()) {
traversable_views.push_back(mini_view);
traversable_views.push_back(mini_view->desk_name_view());
}
}
if (bar_view->new_desk_button()->GetEnabled())
if (features::IsBentoEnabled()) {
auto* new_desk_button =
bar_view->expanded_state_new_desk_button()->new_desk_button();
if (!is_zero_state && new_desk_button->GetEnabled())
traversable_views.push_back(new_desk_button);
} else if (bar_view->new_desk_button()->GetEnabled()) {
traversable_views.push_back(bar_view->new_desk_button());
}
}
for (auto& item : grid->window_list())
traversable_views.push_back(item->overview_item_view());
......
......@@ -7,12 +7,15 @@
#include "ash/public/cpp/ash_features.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/desks/close_desk_button.h"
#include "ash/wm/desks/desk.h"
#include "ash/wm/desks/desk_mini_view.h"
#include "ash/wm/desks/desk_name_view.h"
#include "ash/wm/desks/desks_bar_view.h"
#include "ash/wm/desks/desks_test_util.h"
#include "ash/wm/desks/expanded_state_new_desk_button.h"
#include "ash/wm/desks/new_desk_button.h"
#include "ash/wm/desks/zero_state_button.h"
#include "ash/wm/overview/overview_constants.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/overview/overview_grid.h"
......@@ -743,7 +746,9 @@ TEST_F(BentoOverviewHighlightControllerTest,
ToggleOverview();
const auto* desk_bar_view =
GetDesksBarViewForRoot(Shell::GetPrimaryRootWindow());
const auto* new_desk_button = desk_bar_view->new_desk_button();
ASSERT_FALSE(desk_bar_view->IsZeroState());
const auto* new_desk_button =
desk_bar_view->expanded_state_new_desk_button()->new_desk_button();
const auto* desks_controller = DesksController::Get();
auto check_name_view_at_index = [this](const auto* desk_bar_view, int index) {
......@@ -776,4 +781,54 @@ TEST_F(BentoOverviewHighlightControllerTest,
desks_controller->desks().size());
}
TEST_F(BentoOverviewHighlightControllerTest, ZeroStateOfDesksBar) {
ToggleOverview();
auto* desks_bar_view = GetDesksBarViewForRoot(Shell::GetPrimaryRootWindow());
ASSERT_FALSE(desks_bar_view->IsZeroState());
ASSERT_EQ(2u, desks_bar_view->mini_views().size());
// Remove one desk to enter zero state desks bar.
auto* event_generator = GetEventGenerator();
auto* mini_view = desks_bar_view->mini_views()[1];
event_generator->MoveMouseTo(mini_view->GetBoundsInScreen().CenterPoint());
EXPECT_TRUE(mini_view->close_desk_button()->GetVisible());
event_generator->MoveMouseTo(
mini_view->close_desk_button()->GetBoundsInScreen().CenterPoint());
event_generator->ClickLeftButton();
EXPECT_TRUE(desks_bar_view->IsZeroState());
// Both zero state default desk button and zero state new desk button can be
// focused in overview mode.
SendKey(ui::VKEY_TAB);
EXPECT_EQ(desks_bar_view->zero_state_default_desk_button(),
GetHighlightedView());
SendKey(ui::VKEY_TAB);
EXPECT_EQ(desks_bar_view->zero_state_new_desk_button(), GetHighlightedView());
// Trigger the zero state default desk button will focus on the default desk's
// name view.
SendKey(ui::VKEY_TAB);
EXPECT_EQ(desks_bar_view->zero_state_default_desk_button(),
GetHighlightedView());
SendKey(ui::VKEY_RETURN);
EXPECT_EQ(desks_bar_view->mini_views()[0]->desk_name_view(),
GetHighlightedView());
ToggleOverview();
// Trigger the zero state new desk button will focus on the new created desk's
// name view.
ToggleOverview();
EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
desks_bar_view = GetOverviewSession()
->GetGridWithRootWindow(Shell::GetPrimaryRootWindow())
->desks_bar_view();
EXPECT_TRUE(desks_bar_view->IsZeroState());
SendKey(ui::VKEY_TAB);
SendKey(ui::VKEY_TAB);
EXPECT_EQ(desks_bar_view->zero_state_new_desk_button(), GetHighlightedView());
SendKey(ui::VKEY_RETURN);
EXPECT_EQ(desks_bar_view->mini_views()[1]->desk_name_view(),
GetHighlightedView());
}
} // 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