chromium/ash/wm/overview/overview_test_util.cc

// Copyright 2019 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/wm/overview/overview_test_util.h"

#include "ash/public/cpp/overview_test_api.h"
#include "ash/shell.h"
#include "ash/test/ash_test_util.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/overview/overview_grid.h"
#include "ash/wm/overview/overview_item.h"
#include "ash/wm/overview/overview_item_base.h"
#include "ash/wm/overview/overview_item_view.h"
#include "ash/wm/overview/overview_utils.h"
#include "ash/wm/window_util.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/events/test/event_generator.h"
#include "ui/views/test/views_test_utils.h"

namespace ash {

namespace {

void WaitForOverviewAnimationState(OverviewAnimationState state) {
  // Early out if animations are disabled.
  if (ui::ScopedAnimationDurationScaleMode::duration_multiplier() ==
      ui::ScopedAnimationDurationScaleMode::ZERO_DURATION) {
    return;
  }

  base::RunLoop run_loop;
  OverviewTestApi().WaitForOverviewState(
      state, base::BindLambdaForTesting([&](bool) { run_loop.Quit(); }));
  run_loop.Run();
}

}  // namespace

void ToggleOverview(OverviewEnterExitType type) {
  auto* overview_controller = OverviewController::Get();
  if (overview_controller->InOverviewSession()) {
    overview_controller->EndOverview(OverviewEndAction::kTests, type);
  } else {
    overview_controller->StartOverview(OverviewStartAction::kTests, type);
    RunScheduledLayoutForAllOverviewDeskBars();
  }
}

void WaitForOverviewEnterAnimation() {
  WaitForOverviewAnimationState(
      OverviewAnimationState::kEnterAnimationComplete);
}

void WaitForOverviewExitAnimation() {
  WaitForOverviewAnimationState(OverviewAnimationState::kExitAnimationComplete);
}

void WaitForOverviewEntered() {
  base::RunLoop run_loop;
  OverviewTestApi().WaitForOverviewState(
      OverviewAnimationState::kEnterAnimationComplete,
      base::IgnoreArgs<bool>(run_loop.QuitClosure()));
  run_loop.Run();
}

OverviewGrid* GetOverviewGridForRoot(aura::Window* root) {
  DCHECK(root->IsRootWindow());

  auto* overview_controller = OverviewController::Get();
  CHECK(overview_controller->InOverviewSession());
  return overview_controller->overview_session()->GetGridWithRootWindow(root);
}

const std::vector<std::unique_ptr<OverviewItemBase>>& GetOverviewItemsForRoot(
    int index) {
  return GetOverviewSession()->grid_list()[index]->item_list();
}

std::vector<aura::Window*> GetWindowsListInOverviewGrids() {
  auto* overview_controller = OverviewController::Get();
  CHECK(overview_controller->InOverviewSession());

  std::vector<aura::Window*> windows;
  for (const std::unique_ptr<OverviewGrid>& grid :
       overview_controller->overview_session()->grid_list()) {
    for (const std::unique_ptr<OverviewItemBase>& item : grid->item_list()) {
      for (aura::Window* window : item->GetWindows()) {
        CHECK(window);
        windows.push_back(window);
      }
    }
  }
  return windows;
}

OverviewItemBase* GetOverviewItemForWindow(aura::Window* window) {
  return GetOverviewSession()->GetOverviewItemForWindow(window);
}

void DragItemToPoint(OverviewItemBase* item,
                     const gfx::Point& screen_location,
                     ui::test::EventGenerator* event_generator,
                     bool by_touch_gestures,
                     bool drop) {
  DCHECK(item);

  const gfx::Point item_center =
      gfx::ToRoundedPoint(item->target_bounds().CenterPoint());
  event_generator->set_current_screen_location(item_center);
  if (by_touch_gestures) {
    event_generator->PressTouch();
    // Move the touch by an enough amount in X to engage in the normal drag mode
    // rather than the drag to close mode.
    event_generator->MoveTouchBy(50, 0);
    event_generator->MoveTouch(screen_location);
    if (drop)
      event_generator->ReleaseTouch();
  } else {
    event_generator->PressLeftButton();
    Shell::Get()->cursor_manager()->SetDisplay(
        display::Screen::GetScreen()->GetDisplayNearestPoint(screen_location));
    event_generator->MoveMouseTo(screen_location);
    if (drop)
      event_generator->ReleaseLeftButton();
  }
}

void SendKeyUntilOverviewItemIsFocused(
    ui::KeyboardCode key,
    ui::test::EventGenerator* event_generator) {
  do {
    SendKey(key, event_generator);
  } while (!views::IsViewClass<OverviewItemView>(GetFocusedView()));
}

void WaitForOcclusionStateChange(aura::Window* window,
                                 aura::Window::OcclusionState target_state) {
  while (window->GetOcclusionState() != target_state) {
    base::RunLoop().RunUntilIdle();
  }
}

bool IsWindowInItsCorrespondingOverviewGrid(aura::Window* window) {
  const auto& overview_items =
      GetOverviewGridForRoot(window->GetRootWindow())->item_list();
  for (auto& overview_item : overview_items) {
    if (overview_item->Contains(window)) {
      return true;
    }
  }

  return false;
}

views::View* GetFocusedView() {
  aura::Window* active_window = window_util::GetActiveWindow();
  if (!active_window) {
    return nullptr;
  }

  views::Widget* widget =
      views::Widget::GetWidgetForNativeWindow(active_window);
  return widget ? widget->GetFocusManager()->GetFocusedView() : nullptr;
}

void RunScheduledLayoutForAllOverviewDeskBars() {
  for (const auto& window : Shell::GetAllRootWindows()) {
    OverviewGrid* overview_grid = GetOverviewGridForRoot(window);
    if (overview_grid && overview_grid->desks_widget()) {
      views::test::RunScheduledLayout(overview_grid->desks_widget());
    }
  }
}

}  // namespace ash