Commit 9d6b2ab9 authored by Sammie Quon's avatar Sammie Quon Committed by Commit Bot

overview: Move "No recent items" label out of shield widget.

Shield widget is getting removed. This is step one by moving the cannot
snap window out into its own separate widget owned by overview_session.
Since there is only ever one shown, it doesn't need to be owned by
overviewGrid.

Test: ash_unittests OverviewSessionTest.*
Bug: 942759
Change-Id: I5c9e40763a35d27f2e383effada0f4f6d8791320
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1535131Reviewed-by: default avatarXiaoqian Dai <xdai@chromium.org>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Commit-Queue: Sammie Quon <sammiequon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#644538}
parent 6931ab86
......@@ -39,8 +39,9 @@ enum OverviewAnimationType {
// Used to fade in the drop target when dragging an application to enter
// overview mode.
OVERVIEW_ANIMATION_DROP_TARGET_FADE_IN,
// Used to fade in the shield which covers the work area in and out.
OVERVIEW_ANIMATION_SHIELD_FADE,
// Used to fade in the label which tells users they are in overview mode with
// no window in and out.
OVERVIEW_ANIMATION_NO_RECENTS_FADE,
// Used to animate the selection window which is activated by using tab or the
// arrow keys.
OVERVIEW_ANIMATION_SELECTION_WINDOW_SHADOW,
......
......@@ -21,7 +21,6 @@
#include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_constants.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/wm/desks/desks_bar_view.h"
#include "ash/wm/overview/cleanup_animation_observer.h"
#include "ash/wm/overview/drop_target_view.h"
......@@ -45,15 +44,12 @@
#include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/compositor_extra/shadow.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/views/background.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"
......@@ -78,16 +74,6 @@ constexpr float kOverviewInsetRatio = 0.05f;
// Additional vertical inset reserved for windows in overview mode.
constexpr float kOverviewVerticalInset = 0.1f;
// Values for the no items indicator which appears when opening overview mode
// with no opened windows.
constexpr int kNoItemsIndicatorHeightDp = 32;
constexpr int kNoItemsIndicatorHorizontalPaddingDp = 16;
constexpr int kNoItemsIndicatorRoundingDp = 16;
constexpr int kNoItemsIndicatorVerticalPaddingDp = 8;
constexpr SkColor kNoItemsIndicatorBackgroundColor = SK_ColorBLACK;
constexpr SkColor kNoItemsIndicatorTextColor = SK_ColorWHITE;
constexpr float kNoItemsIndicatorBackgroundOpacity = 0.8f;
// Histogram names for overview enter/exit smoothness in clamshell,
// tablet mode and splitview.
constexpr char kOverviewEnterClamshellHistogram[] =
......@@ -265,38 +251,12 @@ gfx::Rect GetGridBoundsInScreenDuringDragging(aura::Window* dragged_window,
} // namespace
// ShieldView contains the background for overview mode. It also contains text
// which is shown if there are no windows to be displayed.
// This view also takes care of disabling overview mode on:
// - Gesture tap.
// - Mouse release.
// ShieldView takes care of disabling overview mode on gesture tap or mouse
// release. It also shows the virtual desks ui if the feature is enabled.
// TODO(sammiequon): Move disabling to WallpaperView or OverviewSession.
class OverviewGrid::ShieldView : public views::View {
public:
ShieldView() {
label_ = new views::Label(
l10n_util::GetStringUTF16(IDS_ASH_OVERVIEW_NO_RECENT_ITEMS),
views::style::CONTEXT_LABEL);
label_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
label_->SetEnabledColor(kNoItemsIndicatorTextColor);
label_->SetBackgroundColor(kNoItemsIndicatorBackgroundColor);
// |label_container_| is the parent of |label_| which allows the text to
// have padding and rounded edges.
label_container_ = new RoundedRectView(kNoItemsIndicatorRoundingDp,
kNoItemsIndicatorBackgroundColor);
label_container_->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::kVertical,
gfx::Insets(kNoItemsIndicatorVerticalPaddingDp,
kNoItemsIndicatorHorizontalPaddingDp)));
label_container_->AddChildView(label_);
label_container_->SetPaintToLayer();
label_container_->layer()->SetFillsBoundsOpaquely(false);
label_container_->layer()->SetOpacity(kNoItemsIndicatorBackgroundOpacity);
label_container_->SetVisible(false);
AddChildView(label_container_);
}
ShieldView() = default;
~ShieldView() override = default;
const DesksBarView* desks_bar_view() const { return desks_bar_view_; }
......@@ -313,30 +273,13 @@ class OverviewGrid::ShieldView : public views::View {
desks_bar_view_->Init();
}
void SetLabelVisibility(bool visible) {
label_container_->SetVisible(visible);
}
gfx::Rect GetLabelBounds() const {
return label_container_->GetBoundsInScreen();
}
// ShieldView takes up the whole workspace since it changes opacity of the
// whole wallpaper. The bounds of the grid may be smaller in some cases of
// splitview. The label should be centered in the bounds of the grid.
// splitview.
void SetGridBounds(const gfx::Rect& bounds) {
const int label_width = label_->GetPreferredSize().width() +
2 * kNoItemsIndicatorHorizontalPaddingDp;
gfx::Rect label_container_bounds = bounds;
label_container_bounds.ClampToCenteredSize(
gfx::Size(label_width, kNoItemsIndicatorHeightDp));
label_container_->SetBoundsRect(label_container_bounds);
UpdateDesksBarBounds();
}
bool IsLabelVisible() const { return label_container_->visible(); }
protected:
// views::View:
void Layout() override {
......@@ -390,8 +333,6 @@ class OverviewGrid::ShieldView : public views::View {
}
// Owned by views heirarchy.
RoundedRectView* label_container_ = nullptr;
views::Label* label_ = nullptr;
DesksBarView* desks_bar_view_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(ShieldView);
......@@ -571,7 +512,6 @@ void OverviewGrid::PositionWindows(
aura::Window* widget_window = shield_widget_->GetNativeWindow();
const gfx::Rect bounds = widget_window->parent()->bounds();
widget_window->SetBounds(bounds);
ShowNoRecentsWindowMessage(window_list_.empty());
}
if (window_list_.empty())
......@@ -780,15 +720,6 @@ void OverviewGrid::SetSelectionWidgetVisibility(bool visible) {
selection_widget_->Hide();
}
void OverviewGrid::ShowNoRecentsWindowMessage(bool visible) {
// Only show the warning on the grid associated with primary root.
if (root_window_ != Shell::GetPrimaryRootWindow())
return;
if (shield_view_)
shield_view_->SetLabelVisibility(visible);
}
void OverviewGrid::UpdateCannotSnapWarningVisibility() {
for (auto& overview_mode_item : window_list_)
overview_mode_item->UpdateCannotSnapWarningVisibility();
......@@ -1096,10 +1027,8 @@ void OverviewGrid::OnStartingAnimationComplete(bool canceled) {
if (canceled)
return;
if (!shield_widget_) {
if (!shield_widget_)
InitShieldWidget(/*animate=*/true);
ShowNoRecentsWindowMessage(window_list_.empty());
}
for (auto& window : window_list())
window->OnStartingAnimationComplete();
......@@ -1121,17 +1050,6 @@ bool OverviewGrid::ShouldAnimateWallpaper() const {
return true;
}
bool OverviewGrid::IsNoItemsIndicatorLabelVisibleForTesting() {
return shield_view_ && shield_view_->IsLabelVisible();
}
gfx::Rect OverviewGrid::GetNoItemsIndicatorLabelBoundsForTesting() const {
if (!shield_view_)
return gfx::Rect();
return shield_view_->GetLabelBounds();
}
void OverviewGrid::CalculateWindowListAnimationStates(
OverviewItem* selected_item,
OverviewSession::OverviewTransition transition) {
......@@ -1447,7 +1365,7 @@ void OverviewGrid::InitShieldWidget(bool animate) {
// own widgets.
if (animate) {
shield_widget_->SetOpacity(initial_opacity);
ScopedOverviewAnimationSettings settings(OVERVIEW_ANIMATION_SHIELD_FADE,
ScopedOverviewAnimationSettings settings(OVERVIEW_ANIMATION_NO_RECENTS_FADE,
shield_widget_->GetNativeWindow());
shield_widget_->SetOpacity(1.f);
} else {
......
......@@ -111,8 +111,6 @@ class ASH_EXPORT OverviewGrid : public aura::WindowObserver,
// it is dragged.
void SetSelectionWidgetVisibility(bool visible);
void ShowNoRecentsWindowMessage(bool visible);
void UpdateCannotSnapWarningVisibility();
// Called when any OverviewItem on any OverviewGrid has started/ended being
......@@ -165,10 +163,6 @@ class ASH_EXPORT OverviewGrid : public aura::WindowObserver,
// one of the grids windows covers the the entire workspace, true otherwise.
bool ShouldAnimateWallpaper() const;
bool IsNoItemsIndicatorLabelVisibleForTesting();
gfx::Rect GetNoItemsIndicatorLabelBoundsForTesting() const;
// Calculates |should_animate_when_entering_| and
// |should_animate_when_exiting_| of the overview items based on where
// the first MRU window covering the available workspace is found.
......@@ -246,12 +240,12 @@ class ASH_EXPORT OverviewGrid : public aura::WindowObserver,
views::Widget* shield_widget() { return shield_widget_.get(); }
void set_suspend_reposition(bool value) { suspend_reposition_ = value; }
views::Widget* drop_target_widget_for_testing() {
return drop_target_widget_.get();
}
void set_suspend_reposition(bool value) { suspend_reposition_ = value; }
const DesksBarView* GetDesksBarViewForTesting() const;
private:
......@@ -340,7 +334,7 @@ class ASH_EXPORT OverviewGrid : public aura::WindowObserver,
ScopedObserver<aura::Window, OverviewGrid> window_observer_;
ScopedObserver<wm::WindowState, OverviewGrid> window_state_observer_;
// Widget that darkens the screen background.
// Widget that shows the virtual desk UI.
std::unique_ptr<views::Widget> shield_widget_;
// A pointer to |shield_widget_|'s content view.
......
......@@ -15,6 +15,7 @@
#include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_constants.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/overview/overview_delegate.h"
......@@ -22,6 +23,8 @@
#include "ash/wm/overview/overview_item.h"
#include "ash/wm/overview/overview_utils.h"
#include "ash/wm/overview/overview_window_drag_controller.h"
#include "ash/wm/overview/scoped_overview_animation_settings.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/splitview/split_view_drag_indicators.h"
#include "ash/wm/splitview/split_view_utils.h"
#include "ash/wm/switchable_windows.h"
......@@ -32,10 +35,14 @@
#include "base/metrics/user_metrics.h"
#include "base/threading/thread_task_runner_handle.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/base/hit_test.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/display/screen.h"
#include "ui/events/event.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"
#include "ui/wm/core/window_util.h"
......@@ -44,6 +51,16 @@ namespace ash {
namespace {
// Values for the no items indicator which appears when opening overview mode
// with no opened windows.
constexpr int kNoItemsIndicatorHeightDp = 32;
constexpr int kNoItemsIndicatorHorizontalPaddingDp = 16;
constexpr int kNoItemsIndicatorRoundingDp = 16;
constexpr int kNoItemsIndicatorVerticalPaddingDp = 8;
constexpr SkColor kNoItemsIndicatorBackgroundColor =
SkColorSetA(SK_ColorBLACK, 204);
constexpr SkColor kNoItemsIndicatorTextColor = SK_ColorWHITE;
// Triggers a shelf visibility update on all root window controllers.
void UpdateShelfVisibility() {
for (aura::Window* root : Shell::GetAllRootWindows())
......@@ -130,8 +147,64 @@ gfx::Rect GetGridBoundsInScreen(aura::Window* root_window,
return bounds;
}
bool IsWindowDragInProgress() {
auto windows = Shell::Get()->mru_window_tracker()->BuildMruWindowList();
for (auto* window : windows) {
wm::WindowState* window_state = wm::GetWindowState(window);
if (window_state && window_state->is_dragged() &&
(window_state->drag_details()->window_component == HTCLIENT ||
window_state->drag_details()->window_component == HTCAPTION)) {
return true;
}
}
return false;
}
} // namespace
// A label with rounded corners that is displayed when we enter overview with no
// windows.
class OverviewSession::NoWindowsView : public views::View {
public:
NoWindowsView() {
SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::kVertical,
gfx::Insets(kNoItemsIndicatorVerticalPaddingDp,
kNoItemsIndicatorHorizontalPaddingDp)));
SetPaintToLayer(ui::LAYER_SOLID_COLOR);
layer()->SetColor(kNoItemsIndicatorBackgroundColor);
layer()->SetFillsBoundsOpaquely(false);
const std::array<uint32_t, 4> kRadii = {
kNoItemsIndicatorRoundingDp, kNoItemsIndicatorRoundingDp,
kNoItemsIndicatorRoundingDp, kNoItemsIndicatorRoundingDp};
layer()->SetRoundedCornerRadius(kRadii);
layer()->SetIsFastRoundedCorner(true);
label_ = new views::Label(
l10n_util::GetStringUTF16(IDS_ASH_OVERVIEW_NO_RECENT_ITEMS),
views::style::CONTEXT_LABEL);
label_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
label_->SetEnabledColor(kNoItemsIndicatorTextColor);
label_->SetBackgroundColor(kNoItemsIndicatorBackgroundColor);
label_->SetPaintToLayer();
label_->layer()->SetFillsBoundsOpaquely(false);
AddChildView(label_);
}
~NoWindowsView() override = default;
// views::View:
gfx::Size GetPreferredSize() {
int width = label_->GetPreferredSize().width() +
2 * kNoItemsIndicatorHorizontalPaddingDp;
return gfx::Size(width, kNoItemsIndicatorHeightDp);
}
private:
views::Label* label_ = nullptr; // Owned by views hierarchy.
DISALLOW_COPY_AND_ASSIGN(NoWindowsView);
};
OverviewSession::OverviewSession(OverviewDelegate* delegate)
: delegate_(delegate),
restore_focus_window_(wm::GetFocusedWindow()),
......@@ -224,6 +297,8 @@ void OverviewSession::Init(const WindowList& windows,
}
}
MaybeCreateAndPositionNoWindowsWidget();
// Create the widget that will receive focus while in overview mode for
// accessiblity purposes.
overview_focus_widget_ = std::make_unique<views::Widget>();
......@@ -304,6 +379,13 @@ void OverviewSession::Shutdown() {
grid_list_.clear();
UpdateShelfVisibility();
if (no_windows_widget_) {
// Fade out the no windows widget. This animation continues past the
// lifetime of |this|.
FadeOutWidgetAndMaybeSlideOnExit(std::move(no_windows_widget_),
OVERVIEW_ANIMATION_RESTORE_WINDOW);
}
}
void OverviewSession::CancelSelection() {
......@@ -863,6 +945,7 @@ void OverviewSession::OnDisplayBoundsChanged() {
/*divider_changed=*/false));
}
PositionWindows(/*animate=*/false);
MaybeCreateAndPositionNoWindowsWidget();
if (split_view_drag_indicators_)
split_view_drag_indicators_->OnDisplayBoundsChanged();
}
......@@ -875,4 +958,50 @@ bool OverviewSession::IsEmpty() {
return true;
}
void OverviewSession::MaybeCreateAndPositionNoWindowsWidget() {
// Hide the widget if there is an item in overview or there are none but there
// is a window drag in progress. It is possible for a window drag to be in
// progress when we notify that split view has started so check for that case.
if (!IsEmpty() ||
(IsWindowDragInProgress() &&
!Shell::Get()->split_view_controller()->IsSplitViewModeActive())) {
no_windows_widget_.reset();
return;
}
if (!no_windows_widget_) {
// Create and fade in the widget.
no_windows_widget_ = CreateBackgroundWidget(
Shell::GetPrimaryRootWindow(), ui::LAYER_NOT_DRAWN, SK_ColorTRANSPARENT,
0, 0, SK_ColorTRANSPARENT, 0.f, nullptr, true, false);
aura::Window* widget_window = no_windows_widget_->GetNativeWindow();
widget_window->SetName("OverviewNoWindowsLabel");
no_windows_widget_->SetContentsView(new NoWindowsView());
ScopedOverviewAnimationSettings settings(OVERVIEW_ANIMATION_NO_RECENTS_FADE,
widget_window);
no_windows_widget_->SetOpacity(1.f);
}
// The widget is centered in the work area, unless we are in split view with
// one window snapped.
aura::Window* window = no_windows_widget_->GetNativeWindow();
gfx::Rect bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
auto* split_view_controller = Shell::Get()->split_view_controller();
if (split_view_controller->state() == SplitViewController::LEFT_SNAPPED) {
bounds = split_view_controller->GetSnappedWindowBoundsInScreen(
window, SplitViewController::RIGHT);
} else if (split_view_controller->state() ==
SplitViewController::RIGHT_SNAPPED) {
bounds = split_view_controller->GetSnappedWindowBoundsInScreen(
window, SplitViewController::LEFT);
}
NoWindowsView* content_view =
static_cast<NoWindowsView*>(no_windows_widget_->GetContentsView());
DCHECK(content_view);
bounds.ClampToCenteredSize(content_view->GetPreferredSize());
window->SetBounds(bounds);
}
} // namespace ash
......@@ -249,6 +249,10 @@ class ASH_EXPORT OverviewSession : public display::DisplayObserver,
size_t num_items_for_testing() const { return num_items_; }
views::Widget* no_windows_widget_for_testing() {
return no_windows_widget_.get();
}
// display::DisplayObserver:
void OnDisplayRemoved(const display::Display& display) override;
void OnDisplayMetricsChanged(const display::Display& display,
......@@ -267,6 +271,7 @@ class ASH_EXPORT OverviewSession : public display::DisplayObserver,
void OnSplitViewDividerPositionChanged() override;
private:
class NoWindowsView;
friend class OverviewSessionTest;
// |focus|, restores focus to the stored window.
......@@ -286,6 +291,8 @@ class ASH_EXPORT OverviewSession : public display::DisplayObserver,
// Returns true if all its window grids don't have any window item.
bool IsEmpty();
void MaybeCreateAndPositionNoWindowsWidget();
// Tracks observed windows.
base::flat_set<aura::Window*> observed_windows_;
......@@ -308,6 +315,9 @@ class ASH_EXPORT OverviewSession : public display::DisplayObserver,
// mechanism to trigger accessibility events without a focused window.
std::unique_ptr<views::Widget> overview_focus_widget_;
// A widget that is shown if we entered overview without any windows opened.
std::unique_ptr<views::Widget> no_windows_widget_;
// True when performing operations that may cause window activations. This is
// used to prevent handling the resulting expected activation. This is
// initially true until this is initialized.
......
......@@ -1605,51 +1605,30 @@ TEST_F(OverviewSessionTest, OverviewWhileDragging) {
// Verify that the overview no windows indicator appears when entering overview
// mode with no windows.
TEST_F(OverviewSessionTest, OverviewNoWindowsIndicator) {
TEST_F(OverviewSessionTest, NoWindowsIndicator) {
// Verify that by entering overview mode without windows, the no items
// indicator appears.
ToggleOverview();
ASSERT_TRUE(overview_session());
EXPECT_EQ(0u, GetWindowItemsForRoot(0).size());
EXPECT_TRUE(overview_session()
->grid_list_for_testing()[0]
->IsNoItemsIndicatorLabelVisibleForTesting());
ASSERT_EQ(0u, GetWindowItemsForRoot(0).size());
EXPECT_TRUE(overview_session()->no_windows_widget_for_testing());
}
// Verify that the overview no windows indicator position is as expected.
TEST_F(OverviewSessionTest, OverviewNoWindowsIndicatorPosition) {
TEST_F(OverviewSessionTest, NoWindowsIndicatorPosition) {
UpdateDisplay("400x300");
// Midpoint of height minus shelf.
const int expected_y = (300 - ShelfConstants::shelf_size()) / 2;
// Helper to check points. Uses EXPECT_NEAR on each coordinate to account for
// rounding.
auto check_point = [](const gfx::Point& expected, const gfx::Point& actual) {
EXPECT_NEAR(expected.x(), actual.x(), 1);
EXPECT_NEAR(expected.y(), actual.y(), 1);
};
ToggleOverview();
ASSERT_TRUE(overview_session());
views::Widget* no_windows_widget =
overview_session()->no_windows_widget_for_testing();
ASSERT_TRUE(no_windows_widget);
// Verify that originally the label is in the center of the workspace.
OverviewGrid* grid = overview_session()->grid_list_for_testing()[0].get();
check_point(gfx::Point(200, expected_y),
grid->GetNoItemsIndicatorLabelBoundsForTesting().CenterPoint());
// Verify that when grid bounds are on the left, the label is centered on the
// left side of the workspace.
grid->SetBoundsAndUpdatePositions(
gfx::Rect(0, 0, 200, 300 - ShelfConstants::shelf_size()));
check_point(gfx::Point(100, expected_y),
grid->GetNoItemsIndicatorLabelBoundsForTesting().CenterPoint());
// Verify that when grid bounds are on the right, the label is centered on the
// right side of the workspace.
grid->SetBoundsAndUpdatePositions(
gfx::Rect(200, 0, 200, 300 - ShelfConstants::shelf_size()));
check_point(gfx::Point(300, expected_y),
grid->GetNoItemsIndicatorLabelBoundsForTesting().CenterPoint());
// Midpoint of height minus shelf.
int expected_y = (300 - ShelfConstants::shelf_size()) / 2;
EXPECT_EQ(gfx::Point(200, expected_y),
no_windows_widget->GetWindowBoundsInScreen().CenterPoint());
// Verify that after rotating the display, the label is centered in the
// workspace 300x(400-shelf).
......@@ -1658,33 +1637,63 @@ TEST_F(OverviewSessionTest, OverviewNoWindowsIndicatorPosition) {
display_manager()->SetDisplayRotation(
display.id(), display::Display::ROTATE_90,
display::Display::RotationSource::ACTIVE);
check_point(gfx::Point(150, (400 - ShelfConstants::shelf_size()) / 2),
grid->GetNoItemsIndicatorLabelBoundsForTesting().CenterPoint());
expected_y = (400 - ShelfConstants::shelf_size()) / 2;
EXPECT_EQ(gfx::Point(150, (400 - ShelfConstants::shelf_size()) / 2),
no_windows_widget->GetWindowBoundsInScreen().CenterPoint());
}
// Verify that when opening overview mode with multiple displays, the no items
// indicator on the primary grid if there are no windows. Also verify that
// we do not exit overview mode until all the grids are empty.
TEST_F(OverviewSessionTest, OverviewNoWindowsIndicatorMultiDisplay) {
// Helper function to help reduce lines of code. Returns the list of grids
// in overview mode.
auto grids = [this]() -> const std::vector<std::unique_ptr<OverviewGrid>>& {
EXPECT_TRUE(overview_session());
return overview_session()->grid_list_for_testing();
};
TEST_F(OverviewSessionTest, NoWindowsIndicatorPositionSplitview) {
UpdateDisplay("400x300");
std::unique_ptr<aura::Window> window(CreateTestWindow());
ToggleOverview();
ASSERT_TRUE(overview_session());
views::Widget* no_windows_widget =
overview_session()->no_windows_widget_for_testing();
EXPECT_FALSE(no_windows_widget);
// Tests that when snapping a window to the left in splitview, the no windows
// indicator shows up in the middle of the right side of the screen.
auto* split_view_controller = Shell::Get()->split_view_controller();
split_view_controller->SnapWindow(window.get(), SplitViewController::LEFT);
no_windows_widget = overview_session()->no_windows_widget_for_testing();
ASSERT_TRUE(no_windows_widget);
// There is a 8dp divider in splitview, the indicator should take that into
// account.
const int bounds_left = 200 + 4;
int expected_x = bounds_left + (400 - (bounds_left)) / 2;
const int expected_y = (300 - ShelfConstants::shelf_size()) / 2;
EXPECT_EQ(gfx::Point(expected_x, expected_y),
no_windows_widget->GetWindowBoundsInScreen().CenterPoint());
// Tests that when snapping a window to the right in splitview, the no windows
// indicator shows up in the middle of the left side of the screen.
split_view_controller->SnapWindow(window.get(), SplitViewController::RIGHT);
expected_x = /*bounds_right=*/(200 - 4) / 2;
EXPECT_EQ(gfx::Point(expected_x, expected_y),
no_windows_widget->GetWindowBoundsInScreen().CenterPoint());
}
// Verify that when opening overview mode with multiple displays, the no items
// indicator on the primary grid if there are no windows.
TEST_F(OverviewSessionTest, NoWindowsIndicatorPositionMultiDisplay) {
UpdateDisplay("400x400,400x400,400x400");
// Enter overview mode. Verify that the no windows indicator is visible on the
// primary display but not on the other two.
// Enter overview mode. Verify that the no windows indicator is located on the
// primary display.
ToggleOverview();
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(overview_session());
ASSERT_EQ(3u, grids().size());
EXPECT_TRUE(grids()[0]->IsNoItemsIndicatorLabelVisibleForTesting());
EXPECT_FALSE(grids()[1]->IsNoItemsIndicatorLabelVisibleForTesting());
EXPECT_FALSE(grids()[2]->IsNoItemsIndicatorLabelVisibleForTesting());
ToggleOverview();
views::Widget* no_windows_widget =
overview_session()->no_windows_widget_for_testing();
const int expected_y = (400 - ShelfConstants::shelf_size()) / 2;
EXPECT_EQ(gfx::Point(200, expected_y),
no_windows_widget->GetWindowBoundsInScreen().CenterPoint());
}
// Tests that we do not exit overview mode until all the grids are empty.
TEST_F(OverviewSessionTest, ExitOverviewWhenAllGridsEmpty) {
UpdateDisplay("400x400,400x400,400x400");
// Create two windows with widgets (widgets are needed to close the windows
// later in the test), one each on the first two monitors.
......@@ -1700,15 +1709,10 @@ TEST_F(OverviewSessionTest, OverviewNoWindowsIndicatorMultiDisplay) {
// Enter overview mode. Verify that the no windows indicator is not visible on
// any display.
ToggleOverview();
base::RunLoop().RunUntilIdle();
auto& grids = overview_session()->grid_list_for_testing();
ASSERT_TRUE(overview_session());
ASSERT_EQ(3u, grids().size());
EXPECT_FALSE(grids()[0]->IsNoItemsIndicatorLabelVisibleForTesting());
EXPECT_FALSE(grids()[1]->IsNoItemsIndicatorLabelVisibleForTesting());
EXPECT_FALSE(grids()[2]->IsNoItemsIndicatorLabelVisibleForTesting());
EXPECT_FALSE(grids()[0]->empty());
EXPECT_FALSE(grids()[1]->empty());
EXPECT_TRUE(grids()[2]->empty());
ASSERT_EQ(3u, grids.size());
EXPECT_FALSE(overview_session()->no_windows_widget_for_testing());
OverviewItem* item1 = GetWindowItemForWindow(0, window1);
OverviewItem* item2 = GetWindowItemForWindow(1, window2);
......@@ -1719,13 +1723,11 @@ TEST_F(OverviewSessionTest, OverviewNoWindowsIndicatorMultiDisplay) {
item2->CloseWindow();
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(overview_session());
ASSERT_EQ(3u, grids().size());
EXPECT_FALSE(grids()[0]->IsNoItemsIndicatorLabelVisibleForTesting());
EXPECT_FALSE(grids()[1]->IsNoItemsIndicatorLabelVisibleForTesting());
EXPECT_FALSE(grids()[2]->IsNoItemsIndicatorLabelVisibleForTesting());
EXPECT_FALSE(grids()[0]->empty());
EXPECT_TRUE(grids()[1]->empty());
EXPECT_TRUE(grids()[2]->empty());
ASSERT_EQ(3u, grids.size());
EXPECT_FALSE(grids[0]->empty());
EXPECT_TRUE(grids[1]->empty());
EXPECT_TRUE(grids[2]->empty());
EXPECT_FALSE(overview_session()->no_windows_widget_for_testing());
// Close |item1|. Verify that since no windows are open, we exit overview
// mode.
......
......@@ -77,7 +77,7 @@ base::TimeDelta GetAnimationDuration(OverviewAnimationType animation_type) {
return kHomeLauncherTransition;
case OVERVIEW_ANIMATION_DROP_TARGET_FADE_IN:
return kDropTargetFadeIn;
case OVERVIEW_ANIMATION_SHIELD_FADE:
case OVERVIEW_ANIMATION_NO_RECENTS_FADE:
case OVERVIEW_ANIMATION_SELECTION_WINDOW_SHADOW:
case OVERVIEW_ANIMATION_SELECTION_WINDOW:
return kOverviewSelectorTransition;
......@@ -148,7 +148,7 @@ ui::AnimationMetricsReporter* GetMetricsReporter(
case OVERVIEW_ANIMATION_NONE:
case OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_IN_OVERVIEW:
case OVERVIEW_ANIMATION_DROP_TARGET_FADE_IN:
case OVERVIEW_ANIMATION_SHIELD_FADE:
case OVERVIEW_ANIMATION_NO_RECENTS_FADE:
case OVERVIEW_ANIMATION_SELECTION_WINDOW_SHADOW:
case OVERVIEW_ANIMATION_SELECTION_WINDOW:
case OVERVIEW_ANIMATION_OVERVIEW_TITLE_FADE_IN:
......@@ -239,7 +239,7 @@ ScopedOverviewAnimationSettings::ScopedOverviewAnimationSettings(
animation_settings_->SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
break;
case OVERVIEW_ANIMATION_SHIELD_FADE:
case OVERVIEW_ANIMATION_NO_RECENTS_FADE:
case OVERVIEW_ANIMATION_SELECTION_WINDOW_SHADOW:
animation_settings_->SetTweenType(gfx::Tween::EASE_IN_OUT);
animation_settings_->SetPreemptionStrategy(
......
......@@ -108,6 +108,8 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// are adjusted to its minimum size if the desired bounds are smaller than
// its minumum bounds. Note: the snapped window bounds can't be pushed
// outside of the workspace area.
// TODO(xdai): Investigate if we need to pass in |window| as splitview windows
// should always be parented to the primary root window.
gfx::Rect GetSnappedWindowBoundsInParent(aura::Window* window,
SnapPosition snap_position);
gfx::Rect GetSnappedWindowBoundsInScreen(aura::Window* window,
......
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