// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/drag_drop/tab_drag_drop_windows_hider.h"
#include "base/memory/raw_ptr.h"
#include <vector>
#include "ash/app_list/app_list_controller_impl.h"
#include "ash/public/cpp/style/color_provider.h"
#include "ash/public/cpp/window_backdrop.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/root_window_controller.h"
#include "ash/shell.h"
#include "ash/wallpaper/views/wallpaper_widget_controller.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/overview_controller.h"
#include "ui/aura/window.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/wm/core/scoped_animation_disabler.h"
namespace ash {
TabDragDropWindowsHider::TabDragDropWindowsHider(aura::Window* source_window)
: source_window_(source_window) {
DCHECK(source_window_);
root_window_ = source_window_->GetRootWindow();
// Disable the backdrop for |source_window_| during dragging.
WindowBackdrop::Get(source_window_)->DisableBackdrop();
DCHECK(!Shell::Get()->overview_controller()->InOverviewSession());
std::vector<raw_ptr<aura::Window, VectorExperimental>> windows =
Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk);
for (aura::Window* window : windows) {
if (window == source_window_ || window->GetRootWindow() != root_window_) {
continue;
}
window_visibility_map_.emplace(window, window->IsVisible());
if (window->IsVisible()) {
wm::ScopedAnimationDisabler disabler(window);
window->Hide();
}
window->AddObserver(this);
}
// Hide the home launcher if it's enabled during dragging.
Shell::Get()->app_list_controller()->OnWindowDragStarted();
// Blurs the wallpaper background.
RootWindowController::ForWindow(root_window_)
->wallpaper_widget_controller()
->SetWallpaperBlur(ColorProvider::kBackgroundBlurSigma);
// `root_window_` might became nullptr during drag&drop. See b/276736023 for
// details.
root_window_->AddObserver(this);
}
TabDragDropWindowsHider::~TabDragDropWindowsHider() {
// It might be possible that |source_window_| is destroyed during dragging.
if (source_window_) {
WindowBackdrop::Get(source_window_)->RestoreBackdrop();
}
for (auto iter = window_visibility_map_.begin();
iter != window_visibility_map_.end(); ++iter) {
iter->first->RemoveObserver(this);
if (iter->second) {
wm::ScopedAnimationDisabler disabler(iter->first);
iter->first->Show();
}
}
DCHECK(!Shell::Get()->overview_controller()->InOverviewSession());
// May reshow the home launcher after dragging.
Shell::Get()->app_list_controller()->OnWindowDragEnded(
/*animate=*/false);
// Clears the background wallpaper blur.
if (root_window_) {
RootWindowController::ForWindow(root_window_)
->wallpaper_widget_controller()
->SetWallpaperBlur(wallpaper_constants::kClear);
root_window_->RemoveObserver(this);
}
}
void TabDragDropWindowsHider::OnWindowDestroying(aura::Window* window) {
if (window == source_window_) {
source_window_ = nullptr;
return;
}
if (window == root_window_) {
root_window_ = nullptr;
return;
}
window->RemoveObserver(this);
window_visibility_map_.erase(window);
}
void TabDragDropWindowsHider::OnWindowVisibilityChanged(aura::Window* window,
bool visible) {
// The window object is not necessarily the one that is being observed.
// So we only take action if the window is currently being observed.
if (window_visibility_map_.count(window) == 0) {
return;
}
if (visible) {
// Do not let |window| change to visible during the lifetime of |this|.
// Also update |window_visibility_map_| so that we can restore the window
// visibility correctly.
window->Hide();
window_visibility_map_[window] = visible;
}
// else do nothing. It must come from Hide() function above thus should be
// ignored.
}
int TabDragDropWindowsHider::GetWindowVisibilityMapSizeForTesting() const {
return window_visibility_map_.size();
}
} // namespace ash