athena: Fix overview mode for split-view mode.

The changes in this patch:
. If in split-view mode, the left and right windows remain fixed in the overview
  state.
. Selecting either of the left/right windows returns to the split-view mode with
  the same windows.
. Selecting one of the other windows in the stack gets out of split-view mode,
  and switches to the selected window.

In subsequent patches:
. Allow dragging a window from the stack on top of the left/right windows to
  switch that window and remain in split-view mode.
. Allow dragging one of the left/right windows to get out of split-view mode and
  switch to that window.

BUG=404119
R=oshima@chromium.org

Review URL: https://codereview.chromium.org/495193003

Cr-Commit-Position: refs/heads/master@{#292468}
parent 04e05b5d
......@@ -19,6 +19,7 @@ class WindowManagerImplTestApi {
WindowManagerImplTestApi();
~WindowManagerImplTestApi();
athena::WindowManagerImpl* wm() { return wm_; }
athena::WindowListProvider* GetWindowListProvider();
athena::SplitViewController* GetSplitViewController();
......
......@@ -182,7 +182,6 @@ void WindowManagerImpl::SetInOverview(bool active) {
bezel_controller_->set_left_right_delegate(
active ? NULL : split_view_controller_.get());
if (active) {
split_view_controller_->DeactivateSplitMode();
FOR_EACH_OBSERVER(WindowManagerObserver, observers_, OnOverviewModeEnter());
// Re-stack all windows in the order defined by window_list_provider_.
......@@ -191,9 +190,9 @@ void WindowManagerImpl::SetInOverview(bool active) {
for (it = window_list.begin(); it != window_list.end(); ++it)
container_->StackChildAtTop(*it);
overview_ = WindowOverviewMode::Create(
container_.get(), window_list_provider_.get(), this);
container_.get(), window_list_provider_.get(),
split_view_controller_.get(), this);
} else {
CHECK(!split_view_controller_->IsSplitViewModeActive());
overview_.reset();
FOR_EACH_OBSERVER(WindowManagerObserver, observers_, OnOverviewModeExit());
}
......@@ -219,8 +218,33 @@ void WindowManagerImpl::RemoveObserver(WindowManagerObserver* observer) {
}
void WindowManagerImpl::OnSelectWindow(aura::Window* window) {
if (split_view_controller_->IsSplitViewModeActive())
split_view_controller_->DeactivateSplitMode();
wm::ActivateWindow(window);
SetInOverview(false);
// If |window| does not have the size of the work-area, then make sure it is
// resized.
const gfx::Size work_area =
gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area().size();
if (window->GetTargetBounds().size() != work_area) {
const gfx::Rect& window_bounds = window->bounds();
const gfx::Rect desired_bounds(work_area);
gfx::Transform transform;
transform.Translate(desired_bounds.x() - window_bounds.x(),
desired_bounds.y() - window_bounds.y());
transform.Scale(desired_bounds.width() / window_bounds.width(),
desired_bounds.height() / window_bounds.height());
window->layer()->GetAnimator()->AbortAllAnimations();
ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
settings.AddObserver(
new ui::ClosureAnimationObserver(base::Bind(&SetWindowState,
base::Unretained(window),
desired_bounds,
gfx::Transform())));
window->SetTransform(transform);
}
}
void WindowManagerImpl::OnSplitViewMode(aura::Window* left,
......@@ -347,7 +371,7 @@ void WindowManagerImpl::OnTitleDragCompleted(aura::Window* window) {
transform.Translate(window->bounds().x() - next_window->bounds().x(), 0);
next_window->SetTransform(transform);
OnSelectWindow(next_window);
wm::ActivateWindow(next_window);
}
window->Hide();
}
......
......@@ -315,4 +315,24 @@ TEST_F(WindowManagerTest, SplitModeActivationByShortcut) {
EXPECT_EQ(width, w2->bounds().width());
}
TEST_F(WindowManagerTest, OverviewModeFromSplitMode) {
test::WindowManagerImplTestApi wm_api;
aura::test::TestWindowDelegate delegate;
scoped_ptr<aura::Window> w1(CreateTestWindow(&delegate, gfx::Rect()));
scoped_ptr<aura::Window> w2(CreateTestWindow(&delegate, gfx::Rect()));
scoped_ptr<aura::Window> w3(CreateTestWindow(&delegate, gfx::Rect()));
// Get into split-view mode, and then turn on overview mode.
wm_api.GetSplitViewController()->ActivateSplitMode(NULL, NULL);
WindowManager::GetInstance()->ToggleOverview();
EXPECT_TRUE(wm_api.GetSplitViewController()->IsSplitViewModeActive());
EXPECT_EQ(w3.get(), wm_api.GetSplitViewController()->left_window());
EXPECT_EQ(w2.get(), wm_api.GetSplitViewController()->right_window());
WindowOverviewModeDelegate* overview_delegate = wm_api.wm();
overview_delegate->OnSelectWindow(w1.get());
EXPECT_FALSE(wm_api.GetSplitViewController()->IsSplitViewModeActive());
}
} // namespace athena
......@@ -10,6 +10,7 @@
#include "athena/wm/overview_toolbar.h"
#include "athena/wm/public/window_list_provider.h"
#include "athena/wm/split_view_controller.h"
#include "base/bind.h"
#include "base/macros.h"
#include "ui/aura/scoped_window_targeter.h"
......@@ -107,6 +108,7 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
public:
WindowOverviewModeImpl(aura::Window* container,
const WindowListProvider* window_list_provider,
SplitViewController* split_view_controller,
WindowOverviewModeDelegate* delegate)
: container_(container),
window_list_provider_(window_list_provider),
......@@ -115,9 +117,17 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
container,
scoped_ptr<ui::EventTargeter>(
new StaticWindowTargeter(container)))),
dragged_window_(NULL) {
dragged_window_(NULL),
split_({false, NULL, NULL}) {
CHECK(delegate_);
container_->set_target_handler(this);
split_.enabled = split_view_controller->IsSplitViewModeActive();
if (split_.enabled) {
split_.left = split_view_controller->left_window();
split_.right = split_view_controller->right_window();
}
// Prepare the desired transforms for all the windows, and set the initial
// state on the windows.
ComputeTerminalStatesForAllWindows();
......@@ -149,6 +159,15 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
WindowOverviewState* state = new WindowOverviewState;
window->SetProperty(kWindowOverviewState, state);
if (split_.enabled && (window == split_.left || window == split_.right)) {
// Do not let the left/right windows be scrolled.
int x_translate = window->bounds().width() * (1 - kMaxScale) / 2;
state->top.Translate(x_translate, window->bounds().height() * 0.65);
state->top.Scale(kMaxScale, kMaxScale);
state->bottom = state->top;
--index;
continue;
}
UpdateTerminalStateForWindowAtIndex(window, index, windows.size());
}
}
......@@ -185,14 +204,21 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
// Sets the initial position for the windows for the overview mode.
void SetInitialWindowStates() {
aura::Window::Windows windows = window_list_provider_->GetWindowList();
size_t window_count = windows.size();
// The initial overview state of the topmost three windows.
const float kInitialProgress[] = { 0.5f, 0.05f, 0.01f };
for (size_t i = 0; i < window_count; ++i) {
size_t index = 0;
for (aura::Window::Windows::const_reverse_iterator iter = windows.rbegin();
iter != windows.rend();
++iter) {
float progress = 0.f;
aura::Window* window = windows[window_count - 1 - i];
if (i < arraysize(kInitialProgress))
progress = kInitialProgress[i];
aura::Window* window = *iter;
if (split_.enabled && (window == split_.left || window == split_.right)) {
progress = 1;
} else {
if (index < arraysize(kInitialProgress))
progress = kInitialProgress[index];
++index;
}
scoped_refptr<ui::LayerAnimator> animator =
window->layer()->GetAnimator();
......@@ -273,7 +299,10 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
int GetScrollableHeight() const {
const float kScrollableFraction = 0.65f;
return container_->bounds().height() * kScrollableFraction;
const float kScrollableFractionInSplit = 0.5f;
const float fraction =
split_.enabled ? kScrollableFractionInSplit : kScrollableFraction;
return container_->bounds().height() * fraction;
}
void CreateFlingerFor(const ui::GestureEvent& event) {
......@@ -441,13 +470,27 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
RestoreDragWindow();
}
void SelectWindow(aura::Window* window) {
if (!split_.enabled) {
delegate_->OnSelectWindow(window);
} else {
// If the selected window is one of the left/right windows, then keep the
// current state.
if (window == split_.left || window == split_.right) {
delegate_->OnSplitViewMode(split_.left, split_.right);
} else {
delegate_->OnSelectWindow(window);
}
}
}
// ui::EventHandler:
virtual void OnMouseEvent(ui::MouseEvent* mouse) OVERRIDE {
if (mouse->type() == ui::ET_MOUSE_PRESSED) {
aura::Window* select = SelectWindowAt(mouse);
if (select) {
mouse->SetHandled();
delegate_->OnSelectWindow(select);
SelectWindow(select);
}
} else if (mouse->type() == ui::ET_MOUSEWHEEL) {
DoScroll(static_cast<ui::MouseWheelEvent*>(mouse)->y_offset());
......@@ -464,7 +507,7 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
aura::Window* select = SelectWindowAt(gesture);
if (select) {
gesture->SetHandled();
delegate_->OnSelectWindow(select);
SelectWindow(select);
}
} else if (gesture->type() == ui::ET_GESTURE_SCROLL_BEGIN) {
if (std::abs(gesture->details().scroll_x_hint()) >
......@@ -518,7 +561,7 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
const int kMinDistanceForDismissal = 300;
const float kMinScale = 0.6f;
const float kMaxScale = 0.95f;
const float kMaxScale = 0.75f;
const float kMaxOpacity = 1.0f;
const float kMinOpacity = 0.2f;
......@@ -533,6 +576,12 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
gfx::Point dragged_start_location_;
scoped_ptr<OverviewToolbar> overview_toolbar_;
struct {
bool enabled;
aura::Window* left;
aura::Window* right;
} split_;
DISALLOW_COPY_AND_ASSIGN(WindowOverviewModeImpl);
};
......@@ -542,9 +591,11 @@ class WindowOverviewModeImpl : public WindowOverviewMode,
scoped_ptr<WindowOverviewMode> WindowOverviewMode::Create(
aura::Window* container,
const WindowListProvider* window_list_provider,
SplitViewController* split_view_controller,
WindowOverviewModeDelegate* delegate) {
return scoped_ptr<WindowOverviewMode>(
new WindowOverviewModeImpl(container, window_list_provider, delegate));
new WindowOverviewModeImpl(container, window_list_provider,
split_view_controller, delegate));
}
} // namespace athena
......@@ -9,6 +9,7 @@
#include "ui/aura/window.h"
namespace athena {
class SplitViewController;
class WindowListProvider;
class WindowOverviewModeDelegate {
......@@ -31,6 +32,7 @@ class WindowOverviewMode {
static scoped_ptr<WindowOverviewMode> Create(
aura::Window* container,
const WindowListProvider* window_list_provider,
SplitViewController* split_view_controller,
WindowOverviewModeDelegate* delegate);
};
......
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