15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "athena/wm/split_view_controller.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <cmath> 86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "athena/screen/public/screen_manager.h" 106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "athena/wm/public/window_list_provider.h" 116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "athena/wm/public/window_manager.h" 126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/bind.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/aura/scoped_window_targeter.h" 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/aura/window.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/aura/window_targeter.h" 166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/compositor/closure_animation_observer.h" 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/compositor/layer.h" 186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h" 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/events/event_handler.h" 206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/gfx/display.h" 216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/gfx/screen.h" 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/views/background.h" 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/views/layout/box_layout.h" 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/views/widget/root_view.h" 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/views/widget/root_view_targeter.h" 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/views/widget/widget.h" 276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/wm/core/window_util.h" 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/wm/public/activation_client.h" 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace athena { 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace { 3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kDragHandleWidth = 4; 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kDragHandleHeight = 80; 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kDragHandleMargin = 1; 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kDividerWidth = kDragHandleWidth + 2 * kDragHandleMargin; 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Always returns the same target. 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass StaticViewTargeterDelegate : public views::ViewTargeterDelegate { 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci explicit StaticViewTargeterDelegate(views::View* target) : target_(target) {} 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual ~StaticViewTargeterDelegate() {} 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // views::ViewTargeterDelegate: 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual views::View* TargetForRect(views::View* root, 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const gfx::Rect& rect) OVERRIDE { 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return target_; 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Not owned. 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci views::View* target_; 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DISALLOW_COPY_AND_ASSIGN(StaticViewTargeterDelegate); 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Expands the effective target area of the window of the widget containing the 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// specified view. If the view is large enough to begin with, there should be 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// no change from the default targeting behavior. 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass PriorityWindowTargeter : public aura::WindowTargeter, 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public aura::WindowObserver { 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci explicit PriorityWindowTargeter(views::View* priority_view) 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : priority_view_(priority_view) { 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(priority_view->GetWidget()); 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window_ = priority_view->GetWidget()->GetNativeWindow(); 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(window_); 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window_->AddObserver(this); 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual ~PriorityWindowTargeter() { 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window_->RemoveObserver(this); 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // aura::WindowTargeter: 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual ui::EventTarget* FindTargetForLocatedEvent( 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::EventTarget* root, 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::LocatedEvent* event) OVERRIDE { 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!window_ || (event->type() != ui::ET_TOUCH_PRESSED)) 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return WindowTargeter::FindTargetForLocatedEvent(root, event); 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK_EQ(window_, priority_view_->GetWidget()->GetNativeWindow()); 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Bounds of the view in root window's coordinates. 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Rect view_bounds = priority_view_->GetBoundsInScreen(); 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If there is a transform on the window's layer - apply it. 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Transform window_transform = window_->layer()->transform(); 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::RectF transformed_bounds_f = view_bounds; 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window_transform.TransformRect(&transformed_bounds_f); 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Rect transformed_bounds = gfx::Rect(transformed_bounds_f.x(), 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transformed_bounds_f.y(), 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transformed_bounds_f.width(), 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transformed_bounds_f.height()); 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Now expand the bounds to be at least 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // kMinTouchDimension x kMinTouchDimension and target the event to the 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // window if it falls within the expanded bounds 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Point center = transformed_bounds.CenterPoint(); 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Rect extension_rect = gfx::Rect( 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci center.x() - kMinTouchDimension / 2, 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci center.y() - kMinTouchDimension / 2, 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kMinTouchDimension, 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kMinTouchDimension); 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Rect extended_bounds = 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::UnionRects(transformed_bounds, extension_rect); 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (extended_bounds.Contains(event->root_location())) { 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci root->ConvertEventToTarget(window_, event); 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return window_; 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return WindowTargeter::FindTargetForLocatedEvent(root, event); 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // aura::WindowObserver: 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(window, window_); 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window_->RemoveObserver(this); 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window_ = NULL; 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Minimum dimension of a target to be comfortably touchable. 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The effective touch target area of |priority_window_| gets expanded so 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // that it's width and height is ayt least |kMinTouchDimension|. 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int const kMinTouchDimension = 26; 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::Window* window_; 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci views::View* priority_view_; 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DISALLOW_COPY_AND_ASSIGN(PriorityWindowTargeter); 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Returns a target transform required to transform |from| to |to|. 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigfx::Transform GetTransformForBounds(const gfx::Rect& from, 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const gfx::Rect& to) { 13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) gfx::Transform transform; 13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) transform.Translate(to.x() - from.x(), to.y() - from.y()); 13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) transform.Scale(to.width() / static_cast<float>(from.width()), 13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) to.height() / static_cast<float>(from.height())); 14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return transform; 14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool IsLandscapeOrientation(gfx::Display::Rotation rotation) { 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return rotation == gfx::Display::ROTATE_0 || 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci rotation == gfx::Display::ROTATE_180; 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} // namespace 14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)SplitViewController::SplitViewController( 1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) aura::Window* container, 1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) WindowListProvider* window_list_provider) 1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) : state_(INACTIVE), 1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) container_(container), 1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) window_list_provider_(window_list_provider), 1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) left_window_(NULL), 1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) right_window_(NULL), 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_position_(0), 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_scroll_start_position_(0), 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_widget_(NULL), 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci drag_handle_(NULL), 1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) weak_factory_(this) { 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SplitViewController::~SplitViewController() { 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool SplitViewController::CanActivateSplitViewMode() const { 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(mfomitchev): return false in full screen. 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return (!IsSplitViewModeActive() && 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window_list_provider_->GetWindowList().size() >= 2 && 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IsLandscapeOrientation(gfx::Screen::GetNativeScreen()-> 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetDisplayNearestWindow(container_).rotation())); 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool SplitViewController::IsSplitViewModeActive() const { 1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return state_ == ACTIVE; 1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void SplitViewController::ActivateSplitMode(aura::Window* left, 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::Window* right, 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::Window* to_activate) { 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const aura::Window::Windows& windows = window_list_provider_->GetWindowList(); 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::Window::Windows::const_reverse_iterator iter = windows.rbegin(); 1856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (state_ == ACTIVE) { 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!left && left_window_ != right) 1876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) left = left_window_; 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!right && right_window_ != left) 1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) right = right_window_; 1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!left && iter != windows.rend()) { 1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) left = *iter; 1946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) iter++; 1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (left == right && iter != windows.rend()) { 1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) left = *iter; 1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) iter++; 1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!right && iter != windows.rend()) { 2026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) right = *iter; 2036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) iter++; 2046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (right == left && iter != windows.rend()) { 2056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) right = *iter; 2066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) iter++; 2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci to_hide_.clear(); 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (left_window_ && left_window_ != left && left_window_ != right) 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci to_hide_.push_back(left_window_); 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (right_window_ && right_window_ != left && right_window_ != right) 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci to_hide_.push_back(right_window_); 2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci left_window_ = left; 2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci right_window_ = right; 2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_position_ = GetDefaultDividerPosition(); 2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetState(ACTIVE); 2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UpdateLayout(true); 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::client::ActivationClient* activation_client = 2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::client::GetActivationClient(container_->GetRootWindow()); 2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::Window* active_window = activation_client->GetActiveWindow(); 2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (to_activate) { 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(to_activate == left_window_ || to_activate == right_window_); 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci wm::ActivateWindow(to_activate); 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (active_window != left_window_ && 2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci active_window != right_window_) { 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // A window which does not belong to an activity could be active. 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci wm::ActivateWindow(left_window_); 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci active_window = activation_client->GetActiveWindow(); 2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (active_window == left_window_) 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window_list_provider_->StackWindowBehindTo(right_window_, left_window_); 2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci else 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window_list_provider_->StackWindowBehindTo(left_window_, right_window_); 2406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 2416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void SplitViewController::ReplaceWindow(aura::Window* window, 2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) aura::Window* replace_with) { 2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CHECK(IsSplitViewModeActive()); 2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CHECK(replace_with); 2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CHECK(window == left_window_ || window == right_window_); 2476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CHECK(replace_with != left_window_ && replace_with != right_window_); 2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(window_list_provider_->IsWindowInList(replace_with)); 2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::Window* not_replaced = NULL; 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (window == left_window_) { 2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) left_window_ = replace_with; 2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci not_replaced = right_window_; 2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 2556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) right_window_ = replace_with; 2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci not_replaced = left_window_; 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UpdateLayout(false); 2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) wm::ActivateWindow(replace_with); 2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window_list_provider_->StackWindowBehindTo(not_replaced, replace_with); 2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) window->SetTransform(gfx::Transform()); 2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window->Hide(); 2656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 2666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void SplitViewController::DeactivateSplitMode() { 2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK_EQ(ACTIVE, state_); 2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetState(INACTIVE); 2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UpdateLayout(false); 2716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) left_window_ = right_window_ = NULL; 2726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::InitializeDivider() { 2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(!divider_widget_); 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(!drag_handle_); 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci drag_handle_ = CreateDragHandleView(DRAG_HANDLE_HORIZONTAL, 2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this, 2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kDragHandleWidth, 2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kDragHandleHeight); 2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci views::View* content_view = new views::View; 2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content_view->set_background( 2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci views::Background::CreateSolidBackground(SK_ColorBLACK)); 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci views::BoxLayout* layout = 2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new views::BoxLayout(views::BoxLayout::kHorizontal, 2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kDragHandleMargin, 2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kDragHandleMargin, 2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0); 2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); 2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci layout->set_cross_axis_alignment( 2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); 2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content_view->SetLayoutManager(layout); 2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content_view->AddChildView(drag_handle_); 2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_widget_ = new views::Widget(); 2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); 2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci params.parent = container_; 2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci params.bounds = gfx::Rect(-kDividerWidth / 2, 3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0, 3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kDividerWidth, 3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci container_->bounds().height()); 3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_widget_->Init(params); 3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_widget_->SetContentsView(content_view); 3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Install a static view targeter on the root view which always targets 3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // divider_view. 3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(mfomitchev,tdanderson): This should not be needed: 3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 1. crbug.com/414339 - divider_view is the only view and it completely 3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // overlaps the root view. 3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 2. The logic in ViewTargeterDelegate::TargetForRect could be improved to 3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // work better for views that are narrow in one dimension and long in 3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // another dimension. 3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci views::internal::RootView* root_view = 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_cast<views::internal::RootView*>(divider_widget_->GetRootView()); 3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci view_targeter_delegate_.reset(new StaticViewTargeterDelegate(drag_handle_)); 3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci views::ViewTargeter* targeter = 3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new views::RootViewTargeter(view_targeter_delegate_.get(), root_view); 3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_widget_->GetRootView()->SetEventTargeter( 3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<views::ViewTargeter>(targeter)); 3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::HideDivider() { 3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_widget_->Hide(); 3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window_targeter_.reset(); 3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::ShowDivider() { 3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_widget_->Show(); 3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!window_targeter_) { 3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<ui::EventTargeter> window_targeter = 3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<ui::EventTargeter>(new PriorityWindowTargeter(drag_handle_)); 3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci window_targeter_.reset( 3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new aura::ScopedWindowTargeter(container_, window_targeter.Pass())); 3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigfx::Rect SplitViewController::GetLeftAreaBounds() { 33903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) gfx::Rect work_area = 34003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area(); 3411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return gfx::Rect( 3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0, 0, divider_position_ - kDividerWidth / 2, work_area.height()); 34303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 34403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigfx::Rect SplitViewController::GetRightAreaBounds() { 34603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) gfx::Rect work_area = 34703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area(); 34803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int container_width = container_->bounds().width(); 3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return gfx::Rect(divider_position_ + kDividerWidth / 2, 3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0, 3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci container_width - divider_position_ - kDividerWidth / 2, 3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci work_area.height()); 35303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 35403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::SetState(SplitViewController::State state) { 3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (state_ == state) 3576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (divider_widget_ == NULL) 3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci InitializeDivider(); 3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = state; 3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScreenManager::Get()->SetRotationLocked(state_ != INACTIVE); 3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (state == INACTIVE) 3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci HideDivider(); 3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci else 3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ShowDivider(); 3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::UpdateLayout(bool animate) { 3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(left_window_); 3736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CHECK(right_window_); 3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Splitview can be activated from SplitViewController::ActivateSplitMode or 3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // SplitViewController::ScrollEnd. Additionally we don't want to rotate the 3761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // screen while engaging splitview (i.e. state_ == SCROLLING). 3771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (state_ == INACTIVE && !animate) { 3781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Rect work_area = 3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area(); 3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci aura::Window* top_window = window_list_provider_->GetWindowList().back(); 3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (top_window != left_window_) { 3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(mfomitchev): Use to_hide_ instead 3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci left_window_->Hide(); 3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci right_window_->SetBounds(gfx::Rect(work_area.size())); 3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (top_window != right_window_) { 3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci left_window_->SetBounds(gfx::Rect(work_area.size())); 3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(mfomitchev): Use to_hide_ instead 3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci right_window_->Hide(); 3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetWindowTransforms( 3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Transform(), gfx::Transform(), gfx::Transform(), false); 3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 3946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) left_window_->Show(); 3976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) right_window_->Show(); 3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Transform divider_transform; 4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_transform.Translate(divider_position_, 0); 4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (state_ == ACTIVE) { 4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (animate) { 4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Transform left_transform = 4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetTransformForBounds(left_window_->bounds(), GetLeftAreaBounds()); 4051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Transform right_transform = 4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetTransformForBounds(right_window_->bounds(), GetRightAreaBounds()); 4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetWindowTransforms( 4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci left_transform, right_transform, divider_transform, true); 4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci left_window_->SetBounds(GetLeftAreaBounds()); 4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci right_window_->SetBounds(GetRightAreaBounds()); 4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetWindowTransforms( 4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Transform(), gfx::Transform(), divider_transform, false); 4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 4161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Transform left_transform; 4171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Transform right_transform; 4181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Rect left_area_bounds = GetLeftAreaBounds(); 4191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Rect right_area_bounds = GetRightAreaBounds(); 4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If the width of the window is greater than the width of the area which it 4211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // is supposed to occupy - translate the window. Otherwise scale the window 4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // up to fill the target area. 4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (left_window_->bounds().width() >= left_area_bounds.width()) { 4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci left_transform.Translate( 4251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci left_area_bounds.right() - left_window_->bounds().right(), 0); 4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci left_transform = 4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetTransformForBounds(left_window_->bounds(), left_area_bounds); 4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (right_window_->bounds().width() >= right_area_bounds.width()) { 4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci right_transform.Translate( 4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci right_area_bounds.x() - right_window_->bounds().x(), 0); 4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci right_transform = 4351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetTransformForBounds(right_window_->bounds(), right_area_bounds); 4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetWindowTransforms( 4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci left_transform, right_transform, divider_transform, animate); 4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Note: |left_window_| and |right_window_| may be NULL if calling 4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // SetWindowTransforms(): 4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // - caused the in-progress animation to abort. 4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // - started a zero duration animation. 4446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 4456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::SetWindowTransforms( 4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const gfx::Transform& left_transform, 4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const gfx::Transform& right_transform, 4491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const gfx::Transform& divider_transform, 4501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool animate) { 4516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (animate) { 4521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::ScopedLayerAnimationSettings left_settings( 4531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci left_window_->layer()->GetAnimator()); 4541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci left_settings.SetPreemptionStrategy( 4551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 4561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci left_window_->SetTransform(left_transform); 4571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::ScopedLayerAnimationSettings divider_widget_settings( 4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_widget_->GetNativeWindow()->layer()->GetAnimator()); 4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_widget_settings.SetPreemptionStrategy( 4616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 4621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_widget_->GetNativeWindow()->SetTransform(divider_transform); 4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::ScopedLayerAnimationSettings right_settings( 4651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci right_window_->layer()->GetAnimator()); 4661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci right_settings.SetPreemptionStrategy( 4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 4681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci right_settings.AddObserver(new ui::ClosureAnimationObserver( 4696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::Bind(&SplitViewController::OnAnimationCompleted, 4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_factory_.GetWeakPtr()))); 4711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci right_window_->SetTransform(right_transform); 4726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else { 4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci left_window_->SetTransform(left_transform); 4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_widget_->GetNativeWindow()->SetTransform(divider_transform); 4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci right_window_->SetTransform(right_transform); 4766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 4776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 4786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::OnAnimationCompleted() { 48003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Animation can be cancelled when deactivated. 48103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (left_window_ == NULL) 48203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UpdateLayout(false); 4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t i = 0; i < to_hide_.size(); ++i) 4861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci to_hide_[i]->Hide(); 4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci to_hide_.clear(); 4881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (state_ == INACTIVE) { 4901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci left_window_ = NULL; 4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci right_window_ = NULL; 4926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 4936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 4946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint SplitViewController::GetDefaultDividerPosition() { 4961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return container_->GetBoundsInScreen().width() / 2; 4976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 4986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 5006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// BezelController::ScrollDelegate: 5016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 5021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::BezelScrollBegin(BezelController::Bezel bezel, 5031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci float delta) { 5041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!BezelCanScroll()) 5056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 5066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetState(SCROLLING); 5081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const aura::Window::Windows& windows = window_list_provider_->GetWindowList(); 5106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CHECK(windows.size() >= 2); 5116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) aura::Window::Windows::const_reverse_iterator iter = windows.rbegin(); 5126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) aura::Window* current_window = *(iter); 5136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 5146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (delta > 0) { 5156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) right_window_ = current_window; 5166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) left_window_ = *(iter + 1); 5176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else { 5186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) left_window_ = current_window; 5196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) right_window_ = *(iter + 1); 5206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 5216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 5226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CHECK(left_window_); 5236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CHECK(right_window_); 5246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Calculate divider_scroll_start_position_ 5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Screen* screen = gfx::Screen::GetScreenFor(container_); 5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const gfx::Rect& display_bounds = 5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci screen->GetDisplayNearestWindow(container_).bounds(); 5291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Rect container_bounds = container_->GetBoundsInScreen(); 5301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_scroll_start_position_ = 5311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delta > 0 ? display_bounds.x() - container_bounds.x() 5321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : display_bounds.right() - container_bounds.x(); 5331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_position_ = divider_scroll_start_position_ + delta; 5356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UpdateLayout(false); 5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::BezelScrollEnd() { 5396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (state_ != SCROLLING) 5406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 5416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 5426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Max distance from the scroll end position to the middle of the screen where 5436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // we would go into the split view mode. 5446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const int kMaxDistanceFromMiddle = 120; 5451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const int default_divider_position = GetDefaultDividerPosition(); 5461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (std::abs(default_divider_position - divider_position_) <= 5476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) kMaxDistanceFromMiddle) { 5481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_position_ = default_divider_position; 5491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetState(ACTIVE); 5501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (divider_position_ < default_divider_position) { 5511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_position_ = 0; 5521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetState(INACTIVE); 5536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) wm::ActivateWindow(right_window_); 5546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else { 5551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_position_ = container_->GetBoundsInScreen().width(); 5561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetState(INACTIVE); 5576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) wm::ActivateWindow(left_window_); 5586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 5596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UpdateLayout(true); 5605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 5615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::BezelScrollUpdate(float delta) { 5636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (state_ != SCROLLING) 5646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 5651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_position_ = divider_scroll_start_position_ + delta; 5666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UpdateLayout(false); 5675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 5685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool SplitViewController::BezelCanScroll() { 5701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return CanActivateSplitViewMode(); 5711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 5721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/////////////////////////////////////////////////////////////////////////////// 5741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// DragHandleScrollDelegate: 5751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::HandleScrollBegin(float delta) { 5771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(state_ == ACTIVE); 5781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci state_ = SCROLLING; 5791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_scroll_start_position_ = GetDefaultDividerPosition(); 5801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci divider_position_ = divider_scroll_start_position_ + delta; 5811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UpdateLayout(false); 5821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 5831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::HandleScrollEnd() { 5851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BezelScrollEnd(); 5861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 5871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::HandleScrollUpdate(float delta) { 5891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BezelScrollUpdate(delta); 5901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 5911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/////////////////////////////////////////////////////////////////////////////// 5931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// WindowManagerObserver: 5941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::OnOverviewModeEnter() { 5961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (divider_widget_) 5971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci HideDivider(); 5981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 5991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::OnOverviewModeExit() { 6011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (state_ != INACTIVE) 6021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ShowDivider(); 6031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 6041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::OnSplitViewModeEnter() { 6061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 6071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SplitViewController::OnSplitViewModeExit() { 6095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 6105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace athena 612