15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/wm/workspace_controller.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/root_window_controller.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shelf/shelf_layout_manager.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shell.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shell_window_ids.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/wm/window_animations.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/wm/window_state.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/wm/window_util.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/wm/workspace/workspace_event_handler.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/wm/workspace/workspace_layout_manager.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/wm/workspace/workspace_layout_manager_delegate.h"
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/aura/client/aura_constants.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/aura/window.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/compositor/layer.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/wm/core/visibility_controller.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/wm/core/window_animations.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/wm/public/activation_client.h"
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace ash {
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Amount of time to pause before animating anything. Only used during initial
305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// animation (when logging in).
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst int kInitialPauseTimeMS = 750;
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Returns true if there are visible docked windows in the same screen as the
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// |shelf|.
3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool IsDockedAreaVisible(const ShelfLayoutManager* shelf) {
3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return shelf->dock_bounds().width() > 0;
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
38e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
39e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}  // namespace
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WorkspaceController::WorkspaceController(aura::Window* viewport)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : viewport_(viewport),
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      shelf_(NULL),
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      event_handler_(new WorkspaceEventHandler),
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      layout_manager_(new WorkspaceLayoutManager(viewport)) {
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetWindowVisibilityAnimationTransition(
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      viewport_, ::wm::ANIMATE_NONE);
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  viewport_->SetLayoutManager(layout_manager_);
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  viewport_->AddPreTargetHandler(event_handler_.get());
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  viewport_->AddPostTargetHandler(event_handler_.get());
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WorkspaceController::~WorkspaceController() {
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  viewport_->SetLayoutManager(NULL);
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  viewport_->RemovePreTargetHandler(event_handler_.get());
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  viewport_->RemovePostTargetHandler(event_handler_.get());
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WorkspaceWindowState WorkspaceController::GetWindowState() const {
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!shelf_)
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return WORKSPACE_WINDOW_STATE_DEFAULT;
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const aura::Window* topmost_fullscreen_window = GetRootWindowController(
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      viewport_->GetRootWindow())->GetWindowForFullscreenMode();
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (topmost_fullscreen_window &&
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      !wm::GetWindowState(topmost_fullscreen_window)->ignored_by_shelf()) {
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return WORKSPACE_WINDOW_STATE_FULL_SCREEN;
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // These are the container ids of containers which may contain windows that
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // may overlap the launcher shelf and affect its transparency.
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int kWindowContainerIds[] = {kShellWindowId_DefaultContainer,
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     kShellWindowId_DockedContainer, };
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const gfx::Rect shelf_bounds(shelf_->GetIdealBounds());
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool window_overlaps_launcher = false;
76e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  for (size_t idx = 0; idx < arraysize(kWindowContainerIds); idx++) {
77e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const aura::Window* container = Shell::GetContainer(
78e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        viewport_->GetRootWindow(), kWindowContainerIds[idx]);
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const aura::Window::Windows& windows(container->children());
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (aura::Window::Windows::const_iterator i = windows.begin();
810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch         i != windows.end(); ++i) {
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      wm::WindowState* window_state = wm::GetWindowState(*i);
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (window_state->ignored_by_shelf())
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        continue;
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ui::Layer* layer = (*i)->layer();
860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      if (!layer->GetTargetVisibility())
870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        continue;
880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      if (window_state->IsMaximized())
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return WORKSPACE_WINDOW_STATE_MAXIMIZED;
90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      if (!window_overlaps_launcher &&
910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          ((*i)->bounds().Intersects(shelf_bounds))) {
92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        window_overlaps_launcher = true;
930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      }
94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
97effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return (window_overlaps_launcher || IsDockedAreaVisible(shelf_)) ?
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF :
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      WORKSPACE_WINDOW_STATE_DEFAULT;
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid WorkspaceController::SetShelf(ShelfLayoutManager* shelf) {
1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  shelf_ = shelf;
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  layout_manager_->SetShelf(shelf);
10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid WorkspaceController::DoInitialAnimation() {
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  viewport_->Show();
1090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  viewport_->layer()->SetOpacity(0.0f);
111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetTransformForScaleAnimation(
112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      viewport_->layer(), LAYER_SCALE_ANIMATION_ABOVE);
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // In order for pause to work we need to stop animations.
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  viewport_->layer()->GetAnimator()->StopAnimating();
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  {
1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    ui::ScopedLayerAnimationSettings settings(
1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        viewport_->layer()->GetAnimator());
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    settings.SetPreemptionStrategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    viewport_->layer()->GetAnimator()->SchedulePauseForProperties(
1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        base::TimeDelta::FromMilliseconds(kInitialPauseTimeMS),
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ui::LayerAnimationElement::TRANSFORM |
1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            ui::LayerAnimationElement::OPACITY |
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            ui::LayerAnimationElement::BRIGHTNESS |
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            ui::LayerAnimationElement::VISIBILITY);
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    settings.SetTweenType(gfx::Tween::EASE_OUT);
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    settings.SetTransitionDuration(
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(kCrossFadeDurationMS));
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    viewport_->layer()->SetTransform(gfx::Transform());
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    viewport_->layer()->SetOpacity(1.0f);
1330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WorkspaceController::SetMaximizeBackdropDelegate(
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<WorkspaceLayoutManagerDelegate> delegate) {
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  layout_manager_->SetMaximizeBackdropDelegate(delegate.Pass());
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace ash
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)