#include "ash/wm/mru_window_tracker.h"
#include <algorithm>
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/window_restore/window_restore_controller.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "components/app_restore/window_properties.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/base/hit_test.h"
#include "ui/base/mojom/ui_base_types.mojom-shared.h"
#include "ui/base/ui_base_types.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/wm/core/window_util.h"
namespace ash {
class MruWindowTrackerTest : public AshTestBase {
public:
MruWindowTrackerTest() = default;
MruWindowTrackerTest(const MruWindowTrackerTest&) = delete;
MruWindowTrackerTest& operator=(const MruWindowTrackerTest&) = delete;
~MruWindowTrackerTest() override = default;
MruWindowTracker* mru_window_tracker() {
return Shell::Get()->mru_window_tracker();
}
std::unique_ptr<aura::Window> CreateTestWindowRestoredWindow(
int activation_index) {
auto window = CreateTestWindow();
window->SetProperty(app_restore::kActivationIndexKey, activation_index);
WindowRestoreController::Get()->StackWindow(window.get());
return window;
}
};
TEST_F(MruWindowTrackerTest, Basic) {
std::unique_ptr<aura::Window> w1(CreateTestWindow());
std::unique_ptr<aura::Window> w2(CreateTestWindow());
std::unique_ptr<aura::Window> w3(CreateTestWindow());
wm::ActivateWindow(w3.get());
wm::ActivateWindow(w2.get());
wm::ActivateWindow(w1.get());
MruWindowTracker::WindowList window_list =
mru_window_tracker()->BuildMruWindowList(kActiveDesk);
ASSERT_EQ(3u, window_list.size());
EXPECT_EQ(w1.get(), window_list[0]);
EXPECT_EQ(w2.get(), window_list[1]);
EXPECT_EQ(w3.get(), window_list[2]);
}
TEST_F(MruWindowTrackerTest, DraggedWindowsInListOnlyOnce) {
std::unique_ptr<aura::Window> w1(CreateTestWindow());
wm::ActivateWindow(w1.get());
WindowState::Get(w1.get())->CreateDragDetails(gfx::PointF(), HTRIGHT,
::wm::WINDOW_MOVE_SOURCE_TOUCH);
MruWindowTracker::WindowList window_list =
mru_window_tracker()->BuildWindowListIgnoreModal(kActiveDesk);
EXPECT_EQ(1, std::ranges::count(window_list, w1.get()));
}
TEST_F(MruWindowTrackerTest, RestoreMruOrder) {
auto w5 = CreateTestWindowRestoredWindow(5);
EXPECT_THAT(mru_window_tracker()->GetMruWindowsForTesting(),
testing::ElementsAre(w5.get()));
auto w2 = CreateTestWindowRestoredWindow(2);
EXPECT_THAT(mru_window_tracker()->GetMruWindowsForTesting(),
testing::ElementsAre(w5.get(), w2.get()));
auto w3 = CreateTestWindowRestoredWindow(3);
EXPECT_THAT(mru_window_tracker()->GetMruWindowsForTesting(),
testing::ElementsAre(w5.get(), w3.get(), w2.get()));
auto user_created_window = CreateTestWindow();
wm::ActivateWindow(user_created_window.get());
EXPECT_THAT(mru_window_tracker()->GetMruWindowsForTesting(),
testing::ElementsAre(w5.get(), w3.get(), w2.get(),
user_created_window.get()));
auto w4 = CreateTestWindowRestoredWindow(4);
EXPECT_THAT(mru_window_tracker()->GetMruWindowsForTesting(),
testing::ElementsAre(w5.get(), w4.get(), w3.get(), w2.get(),
user_created_window.get()));
auto w1 = CreateTestWindowRestoredWindow(1);
EXPECT_THAT(mru_window_tracker()->GetMruWindowsForTesting(),
testing::ElementsAre(w5.get(), w4.get(), w3.get(), w2.get(),
w1.get(), user_created_window.get()));
}
TEST_F(MruWindowTrackerTest, WindowRestoredWindowsInMruWindowList) {
std::unique_ptr<aura::Window> w1(CreateTestWindow());
w1->SetProperty(app_restore::kLaunchedFromAppRestoreKey, true);
EXPECT_THAT(mru_window_tracker()->BuildMruWindowList(kAllDesks),
testing::ElementsAre(w1.get()));
}
class MruWindowTrackerOrderTest : public MruWindowTrackerTest,
public ::testing::WithParamInterface<bool> {
public:
MruWindowTrackerOrderTest() {}
MruWindowTrackerOrderTest(const MruWindowTrackerOrderTest&) = delete;
MruWindowTrackerOrderTest& operator=(const MruWindowTrackerOrderTest&) =
delete;
~MruWindowTrackerOrderTest() override = default;
MruWindowTracker::WindowList BuildMruWindowList() const {
return GetParam()
? Shell::Get()->mru_window_tracker()->BuildWindowListIgnoreModal(
kActiveDesk)
: Shell::Get()->mru_window_tracker()->BuildMruWindowList(
kActiveDesk);
}
};
TEST_P(MruWindowTrackerOrderTest, Basic) {
std::unique_ptr<aura::Window> w1(CreateTestWindow());
std::unique_ptr<aura::Window> w2(CreateTestWindow());
std::unique_ptr<aura::Window> w3(CreateTestWindow());
w3->SetProperty(aura::client::kZOrderingKey,
ui::ZOrderLevel::kFloatingWindow);
EXPECT_NE(w3->parent(), w1->parent());
std::unique_ptr<aura::Window> w4(CreateTestWindow());
std::unique_ptr<aura::Window> w5(CreateTestWindow());
std::unique_ptr<aura::Window> w6(CreateTestWindow());
wm::ActivateWindow(w6.get());
wm::ActivateWindow(w5.get());
wm::ActivateWindow(w4.get());
wm::ActivateWindow(w3.get());
wm::ActivateWindow(w2.get());
wm::ActivateWindow(w1.get());
WindowState::Get(w1.get())->Minimize();
WindowState::Get(w4.get())->Minimize();
WindowState::Get(w5.get())->Minimize();
EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
MruWindowTracker::WindowList window_list = BuildMruWindowList();
EXPECT_EQ(w2.get(), window_list[0]);
EXPECT_EQ(w1.get(), window_list[1]);
EXPECT_EQ(w3.get(), window_list[2]);
EXPECT_EQ(w4.get(), window_list[3]);
EXPECT_EQ(w5.get(), window_list[4]);
EXPECT_EQ(w6.get(), window_list[5]);
w3->SetProperty(ash::kExcludeInMruKey, true);
window_list = BuildMruWindowList();
EXPECT_EQ(w2.get(), window_list[0]);
EXPECT_EQ(w1.get(), window_list[1]);
EXPECT_EQ(w4.get(), window_list[2]);
EXPECT_EQ(w5.get(), window_list[3]);
EXPECT_EQ(w6.get(), window_list[4]);
auto delegate = std::make_unique<views::WidgetDelegateView>(
views::WidgetDelegateView::CreatePassKey());
delegate->SetModalType(ui::mojom::ModalType::kSystem);
std::unique_ptr<views::Widget> modal =
CreateTestWidget(views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET,
delegate.release(), kShellWindowId_Invalid);
EXPECT_EQ(modal.get()->GetNativeView()->parent()->GetId(),
kShellWindowId_SystemModalContainer);
window_list = BuildMruWindowList();
auto iter = window_list.begin();
if (GetParam()) {
EXPECT_EQ(w2.get(), *iter++);
EXPECT_EQ(w1.get(), *iter++);
EXPECT_EQ(w4.get(), *iter++);
EXPECT_EQ(w5.get(), *iter++);
EXPECT_EQ(w6.get(), *iter++);
}
EXPECT_EQ(iter, window_list.end());
}
INSTANTIATE_TEST_SUITE_P(MruWindowTrackerOrder,
MruWindowTrackerOrderTest,
::testing::Bool());
}