blob: e436114284dfc04d4de1566e6c38ede68af2272d [file] [log] [blame]
// Copyright 2019 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/home_screen/home_screen_controller.h"
#include "ash/home_screen/home_launcher_gesture_handler.h"
#include "ash/home_screen/home_screen_delegate.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shelf/shelf.h"
#include "ash/shell.h"
#include "ash/wallpaper/wallpaper_controller.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/overview/overview_session.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ash/wm/window_state.h"
#include "base/logging.h"
#include "ui/aura/window.h"
#include "ui/display/manager/display_manager.h"
namespace ash {
namespace {
// Minimizes all windows that aren't in the home screen container. Done in
// reverse order to preserve the mru ordering.
// Returns true if any windows are minimized.
bool MinimizeAllWindows() {
bool handled = false;
aura::Window* container = Shell::Get()->GetPrimaryRootWindow()->GetChildById(
kShellWindowId_HomeScreenContainer);
aura::Window::Windows windows =
Shell::Get()->mru_window_tracker()->BuildWindowForCycleList();
for (auto it = windows.rbegin(); it != windows.rend(); it++) {
if (!container->Contains(*it) && !wm::GetWindowState(*it)->IsMinimized()) {
wm::GetWindowState(*it)->Minimize();
handled = true;
}
}
return handled;
}
} // namespace
HomeScreenController::HomeScreenController()
: home_launcher_gesture_handler_(
std::make_unique<HomeLauncherGestureHandler>()) {
Shell::Get()->overview_controller()->AddObserver(this);
Shell::Get()->wallpaper_controller()->AddObserver(this);
}
HomeScreenController::~HomeScreenController() {
Shell::Get()->wallpaper_controller()->RemoveObserver(this);
Shell::Get()->overview_controller()->RemoveObserver(this);
}
bool HomeScreenController::IsHomeScreenAvailable() {
return Shell::Get()
->tablet_mode_controller()
->IsTabletModeWindowManagerEnabled();
}
void HomeScreenController::Show() {
DCHECK(IsHomeScreenAvailable());
if (!Shell::Get()->session_controller()->IsActiveUserSessionStarted())
return;
delegate_->ShowHomeScreenView();
UpdateVisibility();
aura::Window* window = delegate_->GetHomeScreenWindow();
if (window)
Shelf::ForWindow(window)->MaybeUpdateShelfBackground();
}
bool HomeScreenController::GoHome(int64_t display_id) {
DCHECK(IsHomeScreenAvailable());
if (home_launcher_gesture_handler_->ShowHomeLauncher(
Shell::Get()->display_manager()->GetDisplayForId(display_id))) {
return true;
}
if (Shell::Get()->overview_controller()->InOverviewSession()) {
// End overview mode.
Shell::Get()->overview_controller()->ToggleOverview(
OverviewSession::EnterExitOverviewType::kWindowsMinimized);
return true;
}
if (Shell::Get()->split_view_controller()->InSplitViewMode()) {
// End split view mode.
Shell::Get()->split_view_controller()->EndSplitView(
SplitViewController::EndReason::kHomeLauncherPressed);
return true;
}
if (MinimizeAllWindows())
return true;
return false;
}
void HomeScreenController::SetDelegate(HomeScreenDelegate* delegate) {
delegate_ = delegate;
}
void HomeScreenController::OnWindowDragStarted() {
in_window_dragging_ = true;
UpdateVisibility();
}
void HomeScreenController::OnWindowDragEnded() {
in_window_dragging_ = false;
UpdateVisibility();
}
void HomeScreenController::OnOverviewModeStarting() {
// Only animate the home screen when overview mode is using slide animation.
bool animate = Shell::Get()
->overview_controller()
->overview_session()
->enter_exit_overview_type() ==
OverviewSession::EnterExitOverviewType::kWindowsMinimized;
home_screen_presenter_.ScheduleOverviewModeAnimation(true /* start */,
animate);
}
void HomeScreenController::OnOverviewModeEnding(
OverviewSession* overview_session) {
// Animate the launcher if overview mode is sliding out. Let
// OnOverviewModeEndingAnimationComplete handle showing the launcher after
// overview mode finishes animating. Overview however is nullptr by the
// time the animations are finished, so we need to check the animation type
// here.
use_slide_to_exit_overview_ =
overview_session->enter_exit_overview_type() ==
OverviewSession::EnterExitOverviewType::kWindowsMinimized;
}
void HomeScreenController::OnOverviewModeEndingAnimationComplete(
bool canceled) {
if (canceled)
return;
home_screen_presenter_.ScheduleOverviewModeAnimation(
false /* start */, use_slide_to_exit_overview_);
}
void HomeScreenController::OnWallpaperPreviewStarted() {
in_wallpaper_preview_ = true;
UpdateVisibility();
}
void HomeScreenController::OnWallpaperPreviewEnded() {
in_wallpaper_preview_ = false;
UpdateVisibility();
}
void HomeScreenController::UpdateVisibility() {
if (!IsHomeScreenAvailable())
return;
aura::Window* window = delegate_->GetHomeScreenWindow();
if (!window)
return;
const bool in_overview =
Shell::Get()->overview_controller()->InOverviewSession();
if (in_overview || in_wallpaper_preview_ || in_window_dragging_)
window->Hide();
else
window->Show();
}
} // namespace ash