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