146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// found in the LICENSE file.
446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "athena/wm/window_overview_mode.h"
646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include <algorithm>
846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include <functional>
946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include <vector>
1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "athena/wm/overview_toolbar.h"
126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "athena/wm/public/window_list_provider.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "athena/wm/public/window_list_provider_observer.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "athena/wm/split_view_controller.h"
156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/bind.h"
1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/macros.h"
1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/aura/scoped_window_targeter.h"
1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/aura/window.h"
1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/aura/window_delegate.h"
2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/aura/window_property.h"
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/aura/window_targeter.h"
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/aura/window_tree_host.h"
236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/compositor/closure_animation_observer.h"
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/compositor/compositor.h"
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/compositor/compositor_animation_observer.h"
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/events/event_handler.h"
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/events/gestures/fling_curve.h"
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/gfx/frame_time.h"
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/gfx/transform.h"
316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/wm/core/shadow_types.h"
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/wm/core/window_animations.h"
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/wm/core/window_util.h"
3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace {
3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst float kOverviewDefaultScale = 0.75f;
3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistruct WindowOverviewState {
4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // The current overview state of the window. 0.f means the window is at the
4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // topmost position. 1.f means the window is at the bottom-most position.
4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  float progress;
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The top-most and bottom-most vertical position of the window in overview
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // mode.
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  float max_y;
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  float min_y;
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // |split| is set if this window is one of the two split windows in split-view
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // mode.
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool split;
5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)};
5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}  // namespace
5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)DECLARE_WINDOW_PROPERTY_TYPE(WindowOverviewState*)
5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)DEFINE_OWNED_WINDOW_PROPERTY_KEY(WindowOverviewState,
5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 kWindowOverviewState,
5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 NULL)
6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace athena {
6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace {
6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigfx::Transform GetTransformForSplitWindow(aura::Window* window, float scale) {
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const float kScrollWindowPositionInOverview = 0.65f;
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int x_translate = window->bounds().width() * (1 - scale) / 2;
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Transform transform;
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.Translate(
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      x_translate, window->bounds().height() * kScrollWindowPositionInOverview);
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.Scale(scale, scale);
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return transform;
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Gets the transform for the window in its current state.
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigfx::Transform GetTransformForState(aura::Window* window,
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    WindowOverviewState* state) {
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (state->split)
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return GetTransformForSplitWindow(window, kOverviewDefaultScale);
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const float kProgressToStartShrinking = 0.07;
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const float kOverviewScale = 0.75f;
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  float scale = kOverviewScale;
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (state->progress < kProgressToStartShrinking) {
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const float kShrunkMinimumScale = 0.7f;
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scale = gfx::Tween::FloatValueBetween(
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        state->progress / kProgressToStartShrinking,
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        kShrunkMinimumScale,
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        kOverviewScale);
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int container_width = window->parent()->bounds().width();
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int window_width = window->bounds().width();
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int window_x = window->bounds().x();
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  float x_translate = (container_width - (window_width * scale)) / 2 - window_x;
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  float y_translate = gfx::Tween::FloatValueBetween(
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      state->progress, state->min_y, state->max_y);
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Transform transform;
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.Translate(x_translate, y_translate);
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.Scale(scale, scale);
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return transform;
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Sets the progress-state for the window in the overview mode.
10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void SetWindowProgress(aura::Window* window, float progress) {
10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WindowOverviewState* state = window->GetProperty(kWindowOverviewState);
10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  state->progress = progress;
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Transform transform = GetTransformForState(window, state);
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  window->SetTransform(transform);
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid HideWindowIfNotVisible(aura::Window* window,
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            SplitViewController* split_view_controller) {
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool should_hide = true;
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (split_view_controller->IsSplitViewModeActive()) {
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    should_hide = window != split_view_controller->left_window() &&
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                  window != split_view_controller->right_window();
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    should_hide = !wm::IsActiveWindow(window);
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (should_hide)
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    window->Hide();
12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Resets the overview-related state for |window|.
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid RestoreWindowState(aura::Window* window,
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        SplitViewController* split_view_controller) {
12746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  window->ClearProperty(kWindowOverviewState);
12846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  settings.SetPreemptionStrategy(
13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(250));
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  settings.AddObserver(new ui::ClosureAnimationObserver(
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&HideWindowIfNotVisible, window, split_view_controller)));
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  window->SetTransform(gfx::Transform());
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Reset the window opacity in case the user is dragging a window.
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  window->layer()->SetOpacity(1.0f);
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  wm::SetShadowType(window, wm::SHADOW_TYPE_NONE);
14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigfx::RectF GetTransformedBounds(aura::Window* window) {
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Transform transform;
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::RectF bounds = window->bounds();
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.Translate(bounds.x(), bounds.y());
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.PreconcatTransform(window->layer()->transform());
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.Translate(-bounds.x(), -bounds.y());
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  transform.TransformRect(&bounds);
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return bounds;
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid TransformSplitWindowScale(aura::Window* window, float scale) {
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Transform transform = window->layer()->GetTargetTransform();
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (transform.Scale2d() == gfx::Vector2dF(scale, scale))
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  window->SetTransform(GetTransformForSplitWindow(window, scale));
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AnimateWindowTo(aura::Window* animate_window,
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     aura::Window* target_window) {
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ui::ScopedLayerAnimationSettings settings(
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      animate_window->layer()->GetAnimator());
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  settings.SetPreemptionStrategy(
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  WindowOverviewState* target_state =
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      target_window->GetProperty(kWindowOverviewState);
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SetWindowProgress(animate_window, target_state->progress);
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Always returns the same target.
17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class StaticWindowTargeter : public aura::WindowTargeter {
17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public:
17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  explicit StaticWindowTargeter(aura::Window* target) : target_(target) {}
17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ~StaticWindowTargeter() {}
17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private:
18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // aura::WindowTargeter:
18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                              ui::Event* event) OVERRIDE {
18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return target_;
18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ui::EventTarget* FindTargetForLocatedEvent(
18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ui::EventTarget* root,
18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ui::LocatedEvent* event) OVERRIDE {
19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return target_;
19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
19246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
19346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  aura::Window* target_;
19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(StaticWindowTargeter);
19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)};
19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class WindowOverviewModeImpl : public WindowOverviewMode,
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               public ui::EventHandler,
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               public ui::CompositorAnimationObserver,
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               public WindowListProviderObserver {
20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public:
20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WindowOverviewModeImpl(aura::Window* container,
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         WindowListProvider* window_list_provider,
2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         SplitViewController* split_view_controller,
20546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                         WindowOverviewModeDelegate* delegate)
20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      : container_(container),
2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        window_list_provider_(window_list_provider),
2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        split_view_controller_(split_view_controller),
20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        delegate_(delegate),
21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        scoped_targeter_(new aura::ScopedWindowTargeter(
21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            container,
21246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            scoped_ptr<ui::EventTargeter>(
2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                new StaticWindowTargeter(container)))),
2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        dragged_window_(NULL) {
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CHECK(delegate_);
21646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    container_->set_target_handler(this);
21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Prepare the desired transforms for all the windows, and set the initial
21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // state on the windows.
22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ComputeTerminalStatesForAllWindows();
22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    SetInitialWindowStates();
2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    window_list_provider_->AddObserver(this);
22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ~WindowOverviewModeImpl() {
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    window_list_provider_->RemoveObserver(this);
22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    container_->set_target_handler(container_->delegate());
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    RemoveAnimationObserver();
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const aura::Window::Windows& windows =
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        window_list_provider_->GetWindowList();
2326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (windows.empty())
2336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return;
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::for_each(windows.begin(),
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                  windows.end(),
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                  std::bind2nd(std::ptr_fun(&RestoreWindowState),
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               split_view_controller_));
23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private:
24146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Computes the transforms for all windows in both the topmost and bottom-most
24246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // positions. The transforms are set in the |kWindowOverviewState| property of
24346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // the windows.
24446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void ComputeTerminalStatesForAllWindows() {
24546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    size_t index = 0;
24646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const aura::Window::Windows& windows =
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        window_list_provider_->GetWindowList();
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (aura::Window::Windows::const_reverse_iterator iter = windows.rbegin();
25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         iter != windows.rend();
2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)         ++iter, ++index) {
25246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      aura::Window* window = (*iter);
25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      wm::SetShadowType(window, wm::SHADOW_TYPE_RECTANGULAR_ALWAYS_ACTIVE);
25446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
25546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      WindowOverviewState* state = new WindowOverviewState;
25646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      window->SetProperty(kWindowOverviewState, state);
2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (split_view_controller_->IsSplitViewModeActive() &&
2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          (window == split_view_controller_->left_window() ||
2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci           window == split_view_controller_->right_window())) {
2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        // Do not let the left/right windows be scrolled.
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        gfx::Transform transform =
2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            GetTransformForSplitWindow(window, kOverviewDefaultScale);
2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        state->max_y = state->min_y = transform.To2dTranslation().y();
2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        state->split = true;
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        --index;
2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        continue;
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      state->split = false;
26903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      UpdateTerminalStateForWindowAtIndex(window, index, windows.size());
27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Computes the terminal states (i.e. the transforms for the top-most and
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // bottom-most position in the stack) for |window|. |window_count| is the
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // number of windows in the stack, and |index| is the position of the window
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // in the stack (0 being the front-most window).
27703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void UpdateTerminalStateForWindowAtIndex(aura::Window* window,
27803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                           size_t index,
27903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                           size_t window_count) {
28003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const int kGapBetweenWindowsBottom = 10;
28103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const int kGapBetweenWindowsTop = 5;
28203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
28303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    int top = (window_count - index - 1) * kGapBetweenWindowsTop;
28403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    int bottom = GetScrollableHeight() - (index * kGapBetweenWindowsBottom);
28503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
28603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    WindowOverviewState* state = window->GetProperty(kWindowOverviewState);
28703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    CHECK(state);
2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (state->split)
2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    state->min_y = top;
2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    state->max_y = bottom - window->bounds().y();
29203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    state->progress = 0.f;
29303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
29403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Sets the initial position for the windows for the overview mode.
29646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void SetInitialWindowStates() {
29746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // The initial overview state of the topmost three windows.
29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const float kInitialProgress[] = { 0.5f, 0.05f, 0.01f };
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    size_t index = 0;
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const aura::Window::Windows& windows =
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        window_list_provider_->GetWindowList();
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (aura::Window::Windows::const_reverse_iterator iter = windows.rbegin();
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci         iter != windows.rend();
3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci         ++iter) {
30546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      float progress = 0.f;
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      aura::Window* window = *iter;
3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (split_view_controller_->IsSplitViewModeActive() &&
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          (window == split_view_controller_->left_window() ||
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci           window == split_view_controller_->right_window())) {
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        progress = 1;
3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      } else {
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (index < arraysize(kInitialProgress))
3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          progress = kInitialProgress[index];
3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ++index;
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
31646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
31746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      scoped_refptr<ui::LayerAnimator> animator =
31846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          window->layer()->GetAnimator();
31946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
32046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // Unset any in-progress animation.
32103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      animator->AbortAllAnimations();
32203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      window->Show();
32303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      window->SetTransform(gfx::Transform());
32446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // Setup the animation.
32546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      {
32646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        ui::ScopedLayerAnimationSettings settings(animator);
32746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        settings.SetPreemptionStrategy(
32846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
32946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(250));
33046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        SetWindowProgress(window, progress);
33146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
33246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
33346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
33446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
33546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  aura::Window* SelectWindowAt(ui::LocatedEvent* event) {
33646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    CHECK_EQ(container_, event->target());
33746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Find the old targeter to find the target of the event.
33846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ui::EventTarget* window = container_;
33946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ui::EventTargeter* targeter = scoped_targeter_->old_targeter();
34046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    while (!targeter && window->GetParentTarget()) {
34146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      window = window->GetParentTarget();
34246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      targeter = window->GetEventTargeter();
34346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
34446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (!targeter)
34546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return NULL;
34646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    aura::Window* target = static_cast<aura::Window*>(
34746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        targeter->FindTargetForLocatedEvent(container_, event));
34846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    while (target && target->parent() != container_)
34946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      target = target->parent();
35046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return target;
35146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
35246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Scroll the window list by |delta_y| amount. |delta_y| is negative when
354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // scrolling up; and positive when scrolling down.
355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void DoScroll(float delta_y) {
356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const float kEpsilon = 1e-3f;
357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    float delta_y_p = std::abs(delta_y) / GetScrollableHeight();
3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const aura::Window::Windows& windows =
3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        window_list_provider_->GetWindowList();
360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (delta_y < 0) {
361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // Scroll up. Start with the top-most (i.e. behind-most in terms of
362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // z-index) window, and try to scroll them up.
3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      for (aura::Window::Windows::const_iterator iter = windows.begin();
364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           delta_y_p > kEpsilon && iter != windows.end();
365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           ++iter) {
366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        aura::Window* window = (*iter);
367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        WindowOverviewState* state = window->GetProperty(kWindowOverviewState);
368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (state->progress > kEpsilon) {
369f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          // It is possible to scroll |window| up. Scroll it up, and update
370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          // |delta_y_p| for the next window.
371f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          float apply = delta_y_p * state->progress;
372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          SetWindowProgress(window, std::max(0.f, state->progress - apply * 3));
373f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          delta_y_p -= apply;
374f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        }
375f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else {
377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // Scroll down. Start with the bottom-most (i.e. front-most in terms of
378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // z-index) window, and try to scroll them down.
3796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      aura::Window::Windows::const_reverse_iterator iter;
3806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      for (iter = windows.rbegin();
381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           delta_y_p > kEpsilon && iter != windows.rend();
382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           ++iter) {
383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        aura::Window* window = (*iter);
384f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        WindowOverviewState* state = window->GetProperty(kWindowOverviewState);
385f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (1.f - state->progress > kEpsilon) {
386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          // It is possible to scroll |window| down. Scroll it down, and update
387f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          // |delta_y_p| for the next window.
388f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          SetWindowProgress(window, std::min(1.f, state->progress + delta_y_p));
389f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          delta_y_p /= 2.f;
390f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        }
391f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
392f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
393f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
394f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
395f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int GetScrollableHeight() const {
3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const float kScrollableFraction = 0.85f;
3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const float kScrollableFractionInSplit = 0.5f;
3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const float fraction = split_view_controller_->IsSplitViewModeActive()
3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               ? kScrollableFractionInSplit
4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               : kScrollableFraction;
4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return container_->bounds().height() * fraction;
402f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
403f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void CreateFlingerFor(const ui::GestureEvent& event) {
4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gfx::Vector2dF velocity(event.details().velocity_x(),
4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            event.details().velocity_y());
4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    fling_.reset(new ui::FlingCurve(velocity, gfx::FrameTime::Now()));
4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void AddAnimationObserver() {
4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ui::Compositor* compositor = container_->GetHost()->compositor();
4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!compositor->HasAnimationObserver(this))
4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      compositor->AddAnimationObserver(this);
4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void RemoveAnimationObserver() {
4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ui::Compositor* compositor = container_->GetHost()->compositor();
4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (compositor->HasAnimationObserver(this))
4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      compositor->RemoveAnimationObserver(this);
4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  aura::Window* GetSplitWindowDropTarget(const ui::GestureEvent& event) const {
4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!split_view_controller_->IsSplitViewModeActive())
4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return NULL;
4251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CHECK(dragged_window_);
4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CHECK_NE(split_view_controller_->left_window(), dragged_window_);
4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CHECK_NE(split_view_controller_->right_window(), dragged_window_);
4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    aura::Window* window = split_view_controller_->left_window();
4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (GetTransformedBounds(window).Contains(event.location()))
4301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return window;
4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    window = split_view_controller_->right_window();
4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (GetTransformedBounds(window).Contains(event.location()))
4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return window;
4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return NULL;
4351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void DragWindow(const ui::GestureEvent& event) {
4386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    CHECK(dragged_window_);
4396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, event.type());
4406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    CHECK(overview_toolbar_);
4416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    gfx::Vector2dF dragged_distance =
4426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        dragged_start_location_ - event.location();
4436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    WindowOverviewState* dragged_state =
4446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        dragged_window_->GetProperty(kWindowOverviewState);
4456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    CHECK(dragged_state);
4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    gfx::Transform transform =
4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        GetTransformForState(dragged_window_, dragged_state);
4486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    transform.Translate(-dragged_distance.x(), 0);
4496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    dragged_window_->SetTransform(transform);
4506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Update the toolbar.
4526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const int kMinDistanceForActionButtons = 20;
4536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (fabs(dragged_distance.x()) > kMinDistanceForActionButtons)
4546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      overview_toolbar_->ShowActionButtons();
4556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    else
4566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      overview_toolbar_->HideActionButtons();
4576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // See if the touch-point is above one of the action-buttons.
4596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    OverviewToolbar::ActionType new_action =
4606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        overview_toolbar_->GetHighlightAction(event);
4616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // If the touch-point is not above any of the action buttons, then highlight
4636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // the close-button by default, if the user has dragged enough to close the
4646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // window.
4656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (new_action == OverviewToolbar::ACTION_TYPE_NONE) {
4666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (fabs(dragged_distance.x()) > kMinDistanceForDismissal)
4676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        new_action = OverviewToolbar::ACTION_TYPE_CLOSE;
4686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      else
4696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        new_action = OverviewToolbar::ACTION_TYPE_NONE;
4706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
4716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    OverviewToolbar::ActionType previous_action =
4726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        overview_toolbar_->current_action();
4736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    overview_toolbar_->SetHighlightAction(new_action);
4746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    aura::Window* split_drop = GetSplitWindowDropTarget(event);
4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // If the user has selected to get into split-view mode, then show the
4786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // window with full opacity. Otherwise, fade it out as it closes. Animate
4796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // the opacity if transitioning to/from the split-view button.
4806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    bool animate_opacity =
4816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        (new_action != previous_action) &&
4826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        ((new_action == OverviewToolbar::ACTION_TYPE_SPLIT) ||
4836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)         (previous_action == OverviewToolbar::ACTION_TYPE_SPLIT));
4846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    float ratio = std::min(
4856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        1.f, std::abs(dragged_distance.x()) / kMinDistanceForDismissal);
4866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    float opacity =
4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        (new_action == OverviewToolbar::ACTION_TYPE_SPLIT || split_drop)
4886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            ? 1
4896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            : gfx::Tween::FloatValueBetween(ratio, kMaxOpacity, kMinOpacity);
4906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (animate_opacity) {
4916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      ui::ScopedLayerAnimationSettings settings(
4926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          dragged_window_->layer()->GetAnimator());
4936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      dragged_window_->layer()->SetOpacity(opacity);
4946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    } else {
4956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      dragged_window_->layer()->SetOpacity(opacity);
4966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
4971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (split_view_controller_->IsSplitViewModeActive()) {
4991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      float scale = kOverviewDefaultScale;
5001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (split_drop == split_view_controller_->left_window())
5011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        scale = kMaxScaleForSplitTarget;
5021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      TransformSplitWindowScale(split_view_controller_->left_window(), scale);
5031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      scale = kOverviewDefaultScale;
5051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (split_drop == split_view_controller_->right_window())
5061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        scale = kMaxScaleForSplitTarget;
5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      TransformSplitWindowScale(split_view_controller_->right_window(), scale);
5081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
5096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
5106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
5116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  bool ShouldCloseDragWindow(const ui::GestureEvent& event) const {
5126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    gfx::Vector2dF dragged_distance =
5136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        dragged_start_location_ - event.location();
5146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (event.type() == ui::ET_GESTURE_SCROLL_END)
5156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return std::abs(dragged_distance.x()) >= kMinDistanceForDismissal;
5166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    CHECK_EQ(ui::ET_SCROLL_FLING_START, event.type());
5176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const bool dragging_towards_right = dragged_distance.x() < 0;
5186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const bool swipe_towards_right = event.details().velocity_x() > 0;
5196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (dragging_towards_right != swipe_towards_right)
5206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return false;
5216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const float kMinVelocityForDismissal = 500.f;
5226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return std::abs(event.details().velocity_x()) > kMinVelocityForDismissal;
5236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
5246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
5256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void CloseDragWindow(const ui::GestureEvent& gesture) {
5266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Animate |dragged_window_| offscreen first, then destroy it.
5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    {
5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      wm::ScopedHidingAnimationSettings settings(dragged_window_);
5291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      settings.layer_animation_settings()->SetPreemptionStrategy(
5306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
5316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
5321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      WindowOverviewState* dragged_state =
5331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          dragged_window_->GetProperty(kWindowOverviewState);
5341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      CHECK(dragged_state);
5351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::Transform transform = dragged_window_->layer()->transform();
5361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      gfx::RectF transformed_bounds = dragged_window_->bounds();
5371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      transform.TransformRect(&transformed_bounds);
5381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      float transform_x = 0.f;
5391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (gesture.location().x() > dragged_start_location_.x())
5401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        transform_x = container_->bounds().right() - transformed_bounds.x();
5411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      else
5421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        transform_x = -(transformed_bounds.x() + transformed_bounds.width());
5431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      transform.Translate(transform_x / kOverviewDefaultScale, 0);
5441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      dragged_window_->SetTransform(transform);
5451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      dragged_window_->layer()->SetOpacity(kMinOpacity);
5466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
5471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    delete dragged_window_;
5486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    dragged_window_ = NULL;
5496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
5506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
5516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void RestoreDragWindow() {
5526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    CHECK(dragged_window_);
5536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    WindowOverviewState* dragged_state =
5546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        dragged_window_->GetProperty(kWindowOverviewState);
5556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    CHECK(dragged_state);
5566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
5576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ui::ScopedLayerAnimationSettings settings(
5586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        dragged_window_->layer()->GetAnimator());
5596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    settings.SetPreemptionStrategy(
5606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
5611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    dragged_window_->SetTransform(
5621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        GetTransformForState(dragged_window_, dragged_state));
5636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    dragged_window_->layer()->SetOpacity(1.f);
5646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    dragged_window_ = NULL;
5656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
5666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
5676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void EndDragWindow(const ui::GestureEvent& gesture) {
5686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    CHECK(dragged_window_);
5696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    CHECK(overview_toolbar_);
5706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    OverviewToolbar::ActionType action = overview_toolbar_->current_action();
5716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    overview_toolbar_.reset();
5721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (action == OverviewToolbar::ACTION_TYPE_SPLIT) {
5731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      delegate_->OnSelectSplitViewWindow(NULL,
5741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         dragged_window_,
5751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         dragged_window_);
5761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
5771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
5781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // If the window is dropped on one of the left/right windows in split-mode,
5801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // then switch that window.
5811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    aura::Window* split_drop = GetSplitWindowDropTarget(gesture);
5821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (split_drop) {
5831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      aura::Window* left = split_view_controller_->left_window();
5841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      aura::Window* right = split_view_controller_->right_window();
5851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (left == split_drop)
5861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        left = dragged_window_;
5871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      else
5881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        right = dragged_window_;
5891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      delegate_->OnSelectSplitViewWindow(left, right, dragged_window_);
5901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
5911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
5921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (ShouldCloseDragWindow(gesture))
5946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      CloseDragWindow(gesture);
5956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    else
5966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      RestoreDragWindow();
5976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
5986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
5991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void SelectWindow(aura::Window* window) {
6001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!split_view_controller_->IsSplitViewModeActive()) {
6011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      delegate_->OnSelectWindow(window);
6021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    } else {
6031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // If the selected window is one of the left/right windows, then keep the
6041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // current state.
6051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (window == split_view_controller_->left_window() ||
6061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          window == split_view_controller_->right_window()) {
6071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        delegate_->OnSelectSplitViewWindow(
6081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            split_view_controller_->left_window(),
6091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            split_view_controller_->right_window(),
6101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            window);
6111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      } else {
6121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        delegate_->OnSelectWindow(window);
6131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
6141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
6151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
6161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
61746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // ui::EventHandler:
61846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual void OnMouseEvent(ui::MouseEvent* mouse) OVERRIDE {
619f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (mouse->type() == ui::ET_MOUSE_PRESSED) {
620f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      aura::Window* select = SelectWindowAt(mouse);
621f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (select) {
622f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        mouse->SetHandled();
6231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        SelectWindow(select);
624f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
625f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else if (mouse->type() == ui::ET_MOUSEWHEEL) {
626f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      DoScroll(static_cast<ui::MouseWheelEvent*>(mouse)->y_offset());
62746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
62846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
62946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
630f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual void OnScrollEvent(ui::ScrollEvent* scroll) OVERRIDE {
631f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (scroll->type() == ui::ET_SCROLL)
632f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      DoScroll(scroll->y_offset());
633f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
634f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
63546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE {
636f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (gesture->type() == ui::ET_GESTURE_TAP) {
637f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      aura::Window* select = SelectWindowAt(gesture);
638f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (select) {
639f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        gesture->SetHandled();
6401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        SelectWindow(select);
641f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
6426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    } else if (gesture->type() == ui::ET_GESTURE_SCROLL_BEGIN) {
6436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (std::abs(gesture->details().scroll_x_hint()) >
6446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          std::abs(gesture->details().scroll_y_hint()) * 2) {
6456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        dragged_start_location_ = gesture->location();
6466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        dragged_window_ = SelectWindowAt(gesture);
6471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (split_view_controller_->IsSplitViewModeActive() &&
6481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            (dragged_window_ == split_view_controller_->left_window() ||
6491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci             dragged_window_ == split_view_controller_->right_window())) {
6501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          // TODO(sad): Allow closing the left/right window. Closing one of
6511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          // these windows will terminate the split-view mode. Until then, do
6521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          // not allow closing these (since otherwise it gets into an undefined
6531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          // state).
6541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          dragged_window_ = NULL;
6551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
6561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (dragged_window_) {
6581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          // Show the toolbar (for closing a window, or going into split-view
6591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          // mode). If already in split-view mode, then do not show the 'Split'
6601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          // option.
6616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          overview_toolbar_.reset(new OverviewToolbar(container_));
6621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          if (!split_view_controller_->CanActivateSplitViewMode()) {
6631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            overview_toolbar_->DisableAction(
6641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                OverviewToolbar::ACTION_TYPE_SPLIT);
6651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          }
6661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
6676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      }
668f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    } else if (gesture->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
6696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (dragged_window_)
6706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        DragWindow(*gesture);
6716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      else
6726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        DoScroll(gesture->details().scroll_y());
6735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      gesture->SetHandled();
6746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    } else if (gesture->type() == ui::ET_GESTURE_SCROLL_END) {
6756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (dragged_window_)
6766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        EndDragWindow(*gesture);
6775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      gesture->SetHandled();
6786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    } else if (gesture->type() == ui::ET_SCROLL_FLING_START) {
6796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (dragged_window_) {
6806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        EndDragWindow(*gesture);
6816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      } else {
6826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        CreateFlingerFor(*gesture);
6836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        AddAnimationObserver();
6846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      }
6855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      gesture->SetHandled();
6866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    } else if (gesture->type() == ui::ET_GESTURE_TAP_DOWN) {
6876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (fling_) {
6886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        fling_.reset();
6896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        RemoveAnimationObserver();
6906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        gesture->SetHandled();
6916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      }
6926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      dragged_window_ = NULL;
6935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
6945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
6955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // ui::CompositorAnimationObserver:
6975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void OnAnimationStep(base::TimeTicks timestamp) OVERRIDE {
6985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CHECK(fling_);
6995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (fling_->start_timestamp() > timestamp)
7005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
7015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gfx::Vector2dF scroll = fling_->GetScrollAmountAtTime(timestamp);
7025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (scroll.IsZero()) {
7035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      fling_.reset();
7045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      RemoveAnimationObserver();
7055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else {
7065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      DoScroll(scroll.y());
70746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
70846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
70946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // WindowListProviderObserver:
7111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnWindowStackingChanged() OVERRIDE {
7121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Recompute the states of all windows. There isn't enough information at
7131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // this point to do anything more clever.
7141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ComputeTerminalStatesForAllWindows();
7151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SetInitialWindowStates();
7161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
7171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnWindowRemoved(aura::Window* removed_window,
7191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               int index) OVERRIDE {
7201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const aura::Window::Windows& windows =
7211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        window_list_provider_->GetWindowList();
7221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (windows.empty())
7231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
7241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CHECK_LE(index, static_cast<int>(windows.size()));
7251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (index == 0) {
7261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // The back-most window has been removed. Move all the remaining windows
7271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // one step backwards.
7281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      for (int i = windows.size() - 1; i > 0; --i) {
7291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        UpdateTerminalStateForWindowAtIndex(
7301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            windows[i], windows.size() - 1 - i, windows.size());
7311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        AnimateWindowTo(windows[i], windows[i - 1]);
7321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
7331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      UpdateTerminalStateForWindowAtIndex(windows.front(),
7341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                          windows.size() - 1,
7351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                          windows.size());
7361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      AnimateWindowTo(windows.front(), removed_window);
7371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    } else {
7381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Move all windows behind the removed window one step forwards.
7391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      for (int i = 0; i < index - 1; ++i) {
7401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        UpdateTerminalStateForWindowAtIndex(windows[i], windows.size() - 1 - i,
7411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                            windows.size());
7421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        AnimateWindowTo(windows[i], windows[i + 1]);
7431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
7441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      UpdateTerminalStateForWindowAtIndex(windows[index - 1],
7451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                          windows.size() - index,
7461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                          windows.size());
7471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      AnimateWindowTo(windows[index - 1], removed_window);
7481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
7491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
7501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const int kMinDistanceForDismissal = 300;
7526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const float kMaxOpacity = 1.0f;
7536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const float kMinOpacity = 0.2f;
7541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const float kMaxScaleForSplitTarget = 0.9f;
7556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
75646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  aura::Window* container_;
7576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Provider of the stack of windows to show in the overview mode. Not owned.
7581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  WindowListProvider* window_list_provider_;
7591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SplitViewController* split_view_controller_;
7601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
76146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WindowOverviewModeDelegate* delegate_;
76246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<aura::ScopedWindowTargeter> scoped_targeter_;
7635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<ui::FlingCurve> fling_;
76446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  aura::Window* dragged_window_;
7666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  gfx::Point dragged_start_location_;
7676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<OverviewToolbar> overview_toolbar_;
7686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
76946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(WindowOverviewModeImpl);
77046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)};
77146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
77246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}  // namespace
77346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// static
77546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)scoped_ptr<WindowOverviewMode> WindowOverviewMode::Create(
7765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    aura::Window* container,
7771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    WindowListProvider* window_list_provider,
7781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SplitViewController* split_view_controller,
77946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    WindowOverviewModeDelegate* delegate) {
78046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return scoped_ptr<WindowOverviewMode>(
7811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new WindowOverviewModeImpl(container, window_list_provider,
7821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 split_view_controller, delegate));
78346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
78446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
78546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}  // namespace athena
786