blob: 21809a505b358c112bc1be96d75216a50a3f4199 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/common/wm/workspace_controller.h"
#include <utility>
#include "ash/common/shelf/wm_shelf.h"
#include "ash/common/wm/dock/docked_window_layout_manager.h"
#include "ash/common/wm/fullscreen_window_finder.h"
#include "ash/common/wm/window_state.h"
#include "ash/common/wm/wm_window_animations.h"
#include "ash/common/wm/workspace/workspace_event_handler.h"
#include "ash/common/wm/workspace/workspace_layout_manager.h"
#include "ash/common/wm/workspace/workspace_layout_manager_backdrop_delegate.h"
#include "ash/common/wm_root_window_controller.h"
#include "ash/common/wm_shell.h"
#include "ash/common/wm_window.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "base/memory/ptr_util.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
namespace ash {
namespace {
// Amount of time to pause before animating anything. Only used during initial
// animation (when logging in).
const int kInitialPauseTimeMS = 750;
// The duration of the animation that occurs on first login.
const int kInitialAnimationDurationMS = 200;
} // namespace
WorkspaceController::WorkspaceController(WmWindow* viewport)
: viewport_(viewport),
event_handler_(WmShell::Get()->CreateWorkspaceEventHandler(viewport)),
layout_manager_(new WorkspaceLayoutManager(viewport)) {
viewport_->AddObserver(this);
viewport_->SetVisibilityAnimationTransition(::wm::ANIMATE_NONE);
viewport_->SetLayoutManager(base::WrapUnique(layout_manager_));
}
WorkspaceController::~WorkspaceController() {
if (!viewport_)
return;
viewport_->RemoveObserver(this);
viewport_->SetLayoutManager(nullptr);
}
wm::WorkspaceWindowState WorkspaceController::GetWindowState() const {
if (!viewport_ || !viewport_->GetRootWindowController()->HasShelf())
return wm::WORKSPACE_WINDOW_STATE_DEFAULT;
const WmWindow* fullscreen = wm::GetWindowForFullscreenMode(viewport_);
if (fullscreen && !fullscreen->GetWindowState()->ignored_by_shelf())
return wm::WORKSPACE_WINDOW_STATE_FULL_SCREEN;
// These are the container ids of containers which may contain windows that
// may overlap the launcher shelf and affect its transparency.
const int kWindowContainerIds[] = {
kShellWindowId_DefaultContainer, kShellWindowId_DockedContainer,
};
const gfx::Rect shelf_bounds(WmShelf::ForWindow(viewport_)->GetIdealBounds());
bool window_overlaps_launcher = false;
for (size_t i = 0; i < arraysize(kWindowContainerIds); i++) {
WmWindow* container = viewport_->GetRootWindow()->GetChildByShellWindowId(
kWindowContainerIds[i]);
for (WmWindow* window : container->GetChildren()) {
wm::WindowState* window_state = window->GetWindowState();
if (window_state->ignored_by_shelf() ||
(window->GetLayer() && !window->GetLayer()->GetTargetVisibility())) {
continue;
}
if (window_state->IsMaximized())
return wm::WORKSPACE_WINDOW_STATE_MAXIMIZED;
window_overlaps_launcher |= window->GetBounds().Intersects(shelf_bounds);
}
}
// Check if there are visible docked windows in the same display.
DockedWindowLayoutManager* dock = DockedWindowLayoutManager::Get(viewport_);
const bool docked_area_visible = dock && !dock->docked_bounds().IsEmpty();
return (window_overlaps_launcher || docked_area_visible)
? wm::WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF
: wm::WORKSPACE_WINDOW_STATE_DEFAULT;
}
void WorkspaceController::DoInitialAnimation() {
viewport_->Show();
ui::Layer* layer = viewport_->GetLayer();
layer->SetOpacity(0.0f);
SetTransformForScaleAnimation(layer, LAYER_SCALE_ANIMATION_ABOVE);
// In order for pause to work we need to stop animations.
layer->GetAnimator()->StopAnimating();
{
ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
settings.SetPreemptionStrategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
layer->GetAnimator()->SchedulePauseForProperties(
base::TimeDelta::FromMilliseconds(kInitialPauseTimeMS),
ui::LayerAnimationElement::TRANSFORM |
ui::LayerAnimationElement::OPACITY |
ui::LayerAnimationElement::BRIGHTNESS |
ui::LayerAnimationElement::VISIBILITY);
settings.SetTweenType(gfx::Tween::EASE_OUT);
settings.SetTransitionDuration(
base::TimeDelta::FromMilliseconds(kInitialAnimationDurationMS));
layer->SetTransform(gfx::Transform());
layer->SetOpacity(1.0f);
}
}
void WorkspaceController::SetMaximizeBackdropDelegate(
std::unique_ptr<WorkspaceLayoutManagerBackdropDelegate> delegate) {
layout_manager_->SetMaximizeBackdropDelegate(std::move(delegate));
}
void WorkspaceController::OnWindowDestroying(WmWindow* window) {
DCHECK_EQ(window, viewport_);
viewport_->RemoveObserver(this);
viewport_ = nullptr;
// Destroy |event_handler_| too as it depends upon |window|.
event_handler_.reset();
layout_manager_ = nullptr;
}
} // namespace ash