| Index: ash/wm/overview/window_selector_unittest.cc
|
| diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc
|
| index 40dc2b46ce20b01ccd7d5c8c198e7cb5bc5a1b2f..e222fa4eb8e2a70257cd338727f384382b0ea06e 100644
|
| --- a/ash/wm/overview/window_selector_unittest.cc
|
| +++ b/ash/wm/overview/window_selector_unittest.cc
|
| @@ -176,8 +176,8 @@ class WindowSelectorTest : public test::AshTestBase {
|
| }
|
|
|
| bool WindowsOverlapping(aura::Window* window1, aura::Window* window2) {
|
| - gfx::RectF window1_bounds = GetTransformedTargetBounds(window1);
|
| - gfx::RectF window2_bounds = GetTransformedTargetBounds(window2);
|
| + gfx::Rect window1_bounds = GetTransformedTargetBounds(window1);
|
| + gfx::Rect window2_bounds = GetTransformedTargetBounds(window2);
|
| return window1_bounds.Intersects(window2_bounds);
|
| }
|
|
|
| @@ -191,26 +191,33 @@ class WindowSelectorTest : public test::AshTestBase {
|
|
|
| void ToggleOverview() { window_selector_controller()->ToggleOverview(); }
|
|
|
| - gfx::RectF GetTransformedBounds(aura::Window* window) {
|
| + aura::Window* GetOverviewWindowForMinimizedState(int index,
|
| + aura::Window* window) {
|
| + WindowSelectorItem* selector = GetWindowItemForWindow(index, window);
|
| + return WmWindowAura::GetAuraWindow(
|
| + selector->GetOverviewWindowForMinimizedStateForTest());
|
| + }
|
| +
|
| + gfx::Rect GetTransformedBounds(aura::Window* window) {
|
| gfx::RectF bounds(ScreenUtil::ConvertRectToScreen(
|
| window->parent(), window->layer()->bounds()));
|
| gfx::Transform transform(gfx::TransformAboutPivot(
|
| gfx::ToFlooredPoint(bounds.origin()), window->layer()->transform()));
|
| transform.TransformRect(&bounds);
|
| - return bounds;
|
| + return gfx::ToEnclosingRect(bounds);
|
| }
|
|
|
| - gfx::RectF GetTransformedTargetBounds(aura::Window* window) {
|
| + gfx::Rect GetTransformedTargetBounds(aura::Window* window) {
|
| gfx::RectF bounds(ScreenUtil::ConvertRectToScreen(
|
| window->parent(), window->layer()->GetTargetBounds()));
|
| gfx::Transform transform(
|
| gfx::TransformAboutPivot(gfx::ToFlooredPoint(bounds.origin()),
|
| window->layer()->GetTargetTransform()));
|
| transform.TransformRect(&bounds);
|
| - return bounds;
|
| + return gfx::ToEnclosingRect(bounds);
|
| }
|
|
|
| - gfx::RectF GetTransformedBoundsInRootWindow(aura::Window* window) {
|
| + gfx::Rect GetTransformedBoundsInRootWindow(aura::Window* window) {
|
| gfx::RectF bounds = gfx::RectF(gfx::SizeF(window->bounds().size()));
|
| aura::Window* root = window->GetRootWindow();
|
| CHECK(window->layer());
|
| @@ -218,10 +225,10 @@ class WindowSelectorTest : public test::AshTestBase {
|
| gfx::Transform transform;
|
| if (!window->layer()->GetTargetTransformRelativeTo(root->layer(),
|
| &transform)) {
|
| - return gfx::RectF();
|
| + return gfx::Rect();
|
| }
|
| transform.TransformRect(&bounds);
|
| - return bounds;
|
| + return gfx::ToEnclosingRect(bounds);
|
| }
|
|
|
| void ClickWindow(aura::Window* window) {
|
| @@ -329,10 +336,10 @@ class WindowSelectorTest : public test::AshTestBase {
|
| WmWindowAura::GetAuraWindow(window_item->root_window());
|
| EXPECT_TRUE(window_item->Contains(WmWindowAura::Get(window)));
|
| EXPECT_TRUE(root_window->GetBoundsInScreen().Contains(
|
| - ToEnclosingRect(GetTransformedTargetBounds(window))));
|
| - EXPECT_TRUE(root_window->GetBoundsInScreen().Contains(
|
| - ToEnclosingRect(GetTransformedTargetBounds(
|
| - GetCloseButton(window_item)->GetNativeView()))));
|
| + GetTransformedTargetBounds(window)));
|
| + EXPECT_TRUE(
|
| + root_window->GetBoundsInScreen().Contains(GetTransformedTargetBounds(
|
| + GetCloseButton(window_item)->GetNativeView())));
|
| }
|
|
|
| void FilterItems(const base::StringPiece& pattern) {
|
| @@ -454,6 +461,40 @@ TEST_F(WindowSelectorTest, Basic) {
|
| EXPECT_FALSE(aura::client::GetCursorClient(root_window)->IsCursorLocked());
|
| }
|
|
|
| +// Tests activating minimized window.
|
| +TEST_F(WindowSelectorTest, ActivateMinimized) {
|
| + gfx::Rect bounds(0, 0, 400, 400);
|
| + std::unique_ptr<aura::Window> window(CreateWindow(bounds));
|
| +
|
| + wm::WindowState* window_state = wm::GetWindowState(window.get());
|
| + wm::WMEvent minimize_event(wm::WM_EVENT_MINIMIZE);
|
| + window_state->OnWMEvent(&minimize_event);
|
| + EXPECT_FALSE(window->IsVisible());
|
| + EXPECT_EQ(wm::WINDOW_STATE_TYPE_MINIMIZED,
|
| + wm::GetWindowState(window.get())->GetStateType());
|
| +
|
| + ToggleOverview();
|
| +
|
| + EXPECT_FALSE(window->IsVisible());
|
| + EXPECT_EQ(wm::WINDOW_STATE_TYPE_MINIMIZED,
|
| + wm::GetWindowState(window.get())->GetStateType());
|
| + aura::Window* window_for_minimized_window =
|
| + GetOverviewWindowForMinimizedState(0, window.get());
|
| + EXPECT_TRUE(window_for_minimized_window);
|
| +
|
| + const gfx::Point point =
|
| + GetTransformedBoundsInRootWindow(window_for_minimized_window)
|
| + .CenterPoint();
|
| + ui::test::EventGenerator event_generator(window->GetRootWindow(), point);
|
| + event_generator.ClickLeftButton();
|
| +
|
| + EXPECT_FALSE(IsSelecting());
|
| +
|
| + EXPECT_TRUE(window->IsVisible());
|
| + EXPECT_EQ(wm::WINDOW_STATE_TYPE_NORMAL,
|
| + wm::GetWindowState(window.get())->GetStateType());
|
| +}
|
| +
|
| // Tests that entering overview mode with an App-list active properly focuses
|
| // and activates the overview text filter window.
|
| TEST_F(WindowSelectorTest, TextFilterActive) {
|
| @@ -543,8 +584,9 @@ TEST_F(WindowSelectorTest, BasicWithDocked) {
|
| DockedWindowLayoutManager* manager =
|
| DockedWindowLayoutManager::Get(WmWindowAura::Get(docked1.get()));
|
|
|
| - // Docked windows get shown and transformed.
|
| - EXPECT_TRUE(docked2->IsVisible());
|
| + // Minimized docked windows stays invisible.
|
| + EXPECT_FALSE(docked2->IsVisible());
|
| + EXPECT_TRUE(GetOverviewWindowForMinimizedState(0, docked2.get()));
|
|
|
| // Docked area shrinks.
|
| EXPECT_EQ(0, manager->docked_bounds().width());
|
| @@ -613,14 +655,24 @@ TEST_F(WindowSelectorTest, ActivateDockedWindow) {
|
|
|
| ToggleOverview();
|
|
|
| + // Minimized should stay minimized.
|
| + EXPECT_FALSE(docked_window2->IsVisible());
|
| + EXPECT_EQ(wm::WINDOW_STATE_TYPE_DOCKED_MINIMIZED, state2->GetStateType());
|
| +
|
| + aura::Window* window_for_minimized_docked_window2 =
|
| + GetOverviewWindowForMinimizedState(0, docked_window2.get());
|
| + ASSERT_TRUE(window_for_minimized_docked_window2);
|
| +
|
| // Activate |docked_window2| leaving the overview.
|
| - const gfx::RectF rect =
|
| - GetTransformedBoundsInRootWindow(docked_window2.get());
|
| + const gfx::Rect rect =
|
| + GetTransformedBoundsInRootWindow(window_for_minimized_docked_window2);
|
| gfx::Point point(rect.top_right().x() - 50, rect.top_right().y() + 50);
|
| ui::test::EventGenerator event_generator(docked_window2->GetRootWindow(),
|
| point);
|
| event_generator.ClickLeftButton();
|
|
|
| + EXPECT_FALSE(IsSelecting());
|
| +
|
| // Windows' bounds are still the same.
|
| EXPECT_EQ(expected_bounds.ToString(), docked_window1->bounds().ToString());
|
| EXPECT_EQ(expected_bounds.ToString(), docked_window2->bounds().ToString());
|
| @@ -667,16 +719,20 @@ TEST_F(WindowSelectorTest, CloseDockedWindow) {
|
| ToggleOverview();
|
|
|
| // Close |docked_window2| (staying in overview).
|
| - const gfx::RectF rect = GetTransformedBoundsInRootWindow(docked_window2);
|
| + const gfx::Rect rect = GetTransformedBoundsInRootWindow(docked_window2);
|
| gfx::Point point(rect.top_right().x() - 5, rect.top_right().y() + 5);
|
| ui::test::EventGenerator event_generator(docked_window2->GetRootWindow(),
|
| point);
|
| - // Both windows are visible while in overview.
|
| - EXPECT_TRUE(docked_window1->IsVisible());
|
| - EXPECT_EQ(wm::WINDOW_STATE_TYPE_DOCKED, state1->GetStateType());
|
| +
|
| + // Minimized window stays invisible and in the minimized state while in
|
| + // overview.
|
| + EXPECT_FALSE(docked_window1->IsVisible());
|
| + EXPECT_EQ(wm::WINDOW_STATE_TYPE_DOCKED_MINIMIZED, state1->GetStateType());
|
| EXPECT_TRUE(docked_window2->IsVisible());
|
| EXPECT_EQ(wm::WINDOW_STATE_TYPE_DOCKED, state2->GetStateType());
|
|
|
| + EXPECT_TRUE(GetOverviewWindowForMinimizedState(0, docked_window1.get()));
|
| +
|
| event_generator.ClickLeftButton();
|
| // |docked2| widget is closed.
|
| EXPECT_TRUE(docked2->IsClosed());
|
| @@ -725,17 +781,21 @@ TEST_F(WindowSelectorTest, CloseDockedMinimizedWindow) {
|
|
|
| ToggleOverview();
|
|
|
| - // Close |docked_window2| (staying in overview).
|
| - const gfx::RectF rect = GetTransformedBoundsInRootWindow(docked_window2);
|
| - gfx::Point point(rect.top_right().x() - 5, rect.top_right().y() + 5);
|
| - ui::test::EventGenerator event_generator(docked_window2->GetRootWindow(),
|
| - point);
|
| // Both windows are visible while in overview.
|
| EXPECT_TRUE(docked_window1->IsVisible());
|
| EXPECT_EQ(wm::WINDOW_STATE_TYPE_DOCKED, state1->GetStateType());
|
| - EXPECT_TRUE(docked_window2->IsVisible());
|
| - EXPECT_EQ(wm::WINDOW_STATE_TYPE_DOCKED, state2->GetStateType());
|
| + EXPECT_FALSE(docked_window2->IsVisible());
|
| + EXPECT_EQ(wm::WINDOW_STATE_TYPE_DOCKED_MINIMIZED, state2->GetStateType());
|
|
|
| + // Close |docked_window2| (staying in overview).
|
| + aura::Window* window_for_minimized_docked_window2 =
|
| + GetOverviewWindowForMinimizedState(0, docked_window2);
|
| + ASSERT_TRUE(window_for_minimized_docked_window2);
|
| + const gfx::Rect rect =
|
| + GetTransformedBoundsInRootWindow(window_for_minimized_docked_window2);
|
| + gfx::Point point(rect.top_right().x() - 10, rect.top_right().y() - 10);
|
| + ui::test::EventGenerator event_generator(docked_window2->GetRootWindow(),
|
| + point);
|
| event_generator.ClickLeftButton();
|
| // |docked2| widget is closed.
|
| EXPECT_TRUE(docked2->IsClosed());
|
| @@ -764,8 +824,7 @@ TEST_F(WindowSelectorTest, BasicGesture) {
|
| ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
|
| window2.get());
|
| generator.GestureTapAt(
|
| - gfx::ToEnclosingRect(GetTransformedTargetBounds(window2.get()))
|
| - .CenterPoint());
|
| + GetTransformedTargetBounds(window2.get()).CenterPoint());
|
| EXPECT_EQ(window2.get(), GetFocusedWindow());
|
| }
|
|
|
| @@ -784,8 +843,7 @@ TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionRecorded) {
|
| ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
|
| window2.get());
|
| generator.GestureTapAt(
|
| - gfx::ToEnclosingRect(GetTransformedTargetBounds(window2.get()))
|
| - .CenterPoint());
|
| + GetTransformedTargetBounds(window2.get()).CenterPoint());
|
| EXPECT_EQ(
|
| 1, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview));
|
|
|
| @@ -824,8 +882,7 @@ TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionNotRecorded) {
|
| ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
|
| window1.get());
|
| generator.GestureTapAt(
|
| - gfx::ToEnclosingRect(GetTransformedTargetBounds(window1.get()))
|
| - .CenterPoint());
|
| + GetTransformedTargetBounds(window1.get()).CenterPoint());
|
| EXPECT_EQ(
|
| 0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview));
|
|
|
| @@ -862,7 +919,7 @@ TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionWindowClose) {
|
| ToggleOverview();
|
|
|
| aura::Window* window = widget->GetNativeWindow();
|
| - gfx::RectF bounds = GetTransformedBoundsInRootWindow(window);
|
| + gfx::Rect bounds = GetTransformedBoundsInRootWindow(window);
|
| gfx::Point point(bounds.top_right().x() - 1, bounds.top_right().y() + 5);
|
| ui::test::EventGenerator event_generator(window->GetRootWindow(), point);
|
|
|
| @@ -881,8 +938,7 @@ TEST_F(WindowSelectorTest, NoCrashWithDesktopTap) {
|
|
|
| ToggleOverview();
|
|
|
| - gfx::Rect bounds =
|
| - gfx::ToEnclosingRect(GetTransformedBoundsInRootWindow(window.get()));
|
| + gfx::Rect bounds = GetTransformedBoundsInRootWindow(window.get());
|
| ui::test::EventGenerator event_generator(window->GetRootWindow(),
|
| bounds.CenterPoint());
|
|
|
| @@ -910,8 +966,7 @@ TEST_F(WindowSelectorTest, ClickOnWindowDuringTouch) {
|
|
|
| ToggleOverview();
|
|
|
| - gfx::Rect window1_bounds =
|
| - gfx::ToEnclosingRect(GetTransformedBoundsInRootWindow(window1.get()));
|
| + gfx::Rect window1_bounds = GetTransformedBoundsInRootWindow(window1.get());
|
| ui::test::EventGenerator event_generator(window1->GetRootWindow(),
|
| window1_bounds.CenterPoint());
|
|
|
| @@ -960,7 +1015,7 @@ TEST_F(WindowSelectorTest, WindowDoesNotReceiveEvents) {
|
| ToggleOverview();
|
|
|
| // The bounds have changed, take that into account.
|
| - gfx::RectF bounds = GetTransformedBoundsInRootWindow(window.get());
|
| + gfx::Rect bounds = GetTransformedBoundsInRootWindow(window.get());
|
| gfx::Point point2(bounds.x() + 10, bounds.y() + 10);
|
| ui::MouseEvent event2(ui::ET_MOUSE_PRESSED, point2, point2,
|
| ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
|
| @@ -974,16 +1029,62 @@ TEST_F(WindowSelectorTest, CloseButton) {
|
| std::unique_ptr<views::Widget> widget =
|
| CreateWindowWidget(gfx::Rect(0, 0, 400, 400));
|
|
|
| + std::unique_ptr<views::Widget> minimized_widget =
|
| + CreateWindowWidget(gfx::Rect(400, 0, 400, 400));
|
| + minimized_widget->Minimize();
|
| +
|
| ToggleOverview();
|
|
|
| aura::Window* window = widget->GetNativeWindow();
|
| - gfx::RectF bounds = GetTransformedBoundsInRootWindow(window);
|
| + gfx::Rect bounds = GetTransformedBoundsInRootWindow(window);
|
| gfx::Point point(bounds.top_right().x() - 1, bounds.top_right().y() + 5);
|
| ui::test::EventGenerator event_generator(window->GetRootWindow(), point);
|
|
|
| EXPECT_FALSE(widget->IsClosed());
|
| event_generator.ClickLeftButton();
|
| EXPECT_TRUE(widget->IsClosed());
|
| +
|
| + EXPECT_TRUE(IsSelecting());
|
| +
|
| + aura::Window* window_for_minimized_window =
|
| + GetOverviewWindowForMinimizedState(0,
|
| + minimized_widget->GetNativeWindow());
|
| + ASSERT_TRUE(window_for_minimized_window);
|
| + const gfx::Rect rect =
|
| + GetTransformedBoundsInRootWindow(window_for_minimized_window);
|
| +
|
| + event_generator.MoveMouseTo(
|
| + gfx::Point(rect.top_right().x() - 10, rect.top_right().y() - 10));
|
| +
|
| + EXPECT_FALSE(minimized_widget->IsClosed());
|
| + event_generator.ClickLeftButton();
|
| + EXPECT_TRUE(minimized_widget->IsClosed());
|
| +
|
| + // All minimized windows are closed, so it should exit overview mode.
|
| + RunAllPendingInMessageLoop();
|
| + EXPECT_FALSE(IsSelecting());
|
| +}
|
| +
|
| +// Tests minimizing/unminimizing in overview mode.
|
| +TEST_F(WindowSelectorTest, MinimizeUnminimizei) {
|
| + std::unique_ptr<views::Widget> widget =
|
| + CreateWindowWidget(gfx::Rect(0, 0, 400, 400));
|
| + aura::Window* window = widget->GetNativeWindow();
|
| +
|
| + ToggleOverview();
|
| +
|
| + EXPECT_FALSE(GetOverviewWindowForMinimizedState(0, window));
|
| + widget->Minimize();
|
| + EXPECT_TRUE(widget->IsMinimized());
|
| + EXPECT_TRUE(IsSelecting());
|
| +
|
| + EXPECT_TRUE(GetOverviewWindowForMinimizedState(0, window));
|
| +
|
| + widget->Restore();
|
| + EXPECT_FALSE(widget->IsMinimized());
|
| +
|
| + EXPECT_FALSE(GetOverviewWindowForMinimizedState(0, window));
|
| + EXPECT_TRUE(IsSelecting());
|
| }
|
|
|
| // Tests that clicking on the close button on a secondary display effectively
|
| @@ -1017,7 +1118,7 @@ TEST_F(WindowSelectorTest, CloseButtonOnMultipleDisplay) {
|
| ToggleOverview();
|
|
|
| aura::Window* window2 = widget->GetNativeWindow();
|
| - gfx::RectF bounds = GetTransformedBoundsInRootWindow(window2);
|
| + gfx::Rect bounds = GetTransformedBoundsInRootWindow(window2);
|
| gfx::Point point(bounds.top_right().x() - 1, bounds.top_right().y() + 5);
|
| ui::test::EventGenerator event_generator(window2->GetRootWindow(), point);
|
|
|
| @@ -1192,11 +1293,9 @@ TEST_F(WindowSelectorTest, BoundsChangeDuringOverview) {
|
| // Use overview headers above the window in this test.
|
| window->SetProperty(aura::client::kTopViewInset, 0);
|
| ToggleOverview();
|
| - gfx::Rect overview_bounds =
|
| - ToEnclosingRect(GetTransformedTargetBounds(window.get()));
|
| + gfx::Rect overview_bounds = GetTransformedTargetBounds(window.get());
|
| window->SetBounds(gfx::Rect(200, 0, 200, 200));
|
| - gfx::Rect new_overview_bounds =
|
| - ToEnclosingRect(GetTransformedTargetBounds(window.get()));
|
| + gfx::Rect new_overview_bounds = GetTransformedTargetBounds(window.get());
|
| EXPECT_EQ(overview_bounds.x(), new_overview_bounds.x());
|
| EXPECT_EQ(overview_bounds.y(), new_overview_bounds.y());
|
| EXPECT_EQ(overview_bounds.width(), new_overview_bounds.width());
|
| @@ -1269,8 +1368,7 @@ TEST_F(WindowSelectorTest, LastWindowDestroyed) {
|
| TEST_F(WindowSelectorTest, QuickReentryRestoresInitialTransform) {
|
| gfx::Rect bounds(0, 0, 400, 400);
|
| std::unique_ptr<aura::Window> window(CreateWindow(bounds));
|
| - gfx::Rect initial_bounds =
|
| - ToEnclosingRect(GetTransformedBounds(window.get()));
|
| + gfx::Rect initial_bounds = GetTransformedBounds(window.get());
|
| ToggleOverview();
|
| // Quickly exit and reenter overview mode. The window should still be
|
| // animating when we reenter. We cannot short circuit animations for this but
|
| @@ -1281,12 +1379,10 @@ TEST_F(WindowSelectorTest, QuickReentryRestoresInitialTransform) {
|
| ToggleOverview();
|
| ToggleOverview();
|
| }
|
| - EXPECT_NE(initial_bounds,
|
| - ToEnclosingRect(GetTransformedTargetBounds(window.get())));
|
| + EXPECT_NE(initial_bounds, GetTransformedTargetBounds(window.get()));
|
| ToggleOverview();
|
| EXPECT_FALSE(IsSelecting());
|
| - EXPECT_EQ(initial_bounds,
|
| - ToEnclosingRect(GetTransformedTargetBounds(window.get())));
|
| + EXPECT_EQ(initial_bounds, GetTransformedTargetBounds(window.get()));
|
| }
|
|
|
| // Tests that windows with modal child windows are transformed with the modal
|
| @@ -1301,8 +1397,8 @@ TEST_F(WindowSelectorTest, ModalChild) {
|
| ToggleOverview();
|
| EXPECT_TRUE(window1->IsVisible());
|
| EXPECT_TRUE(child1->IsVisible());
|
| - EXPECT_EQ(ToEnclosingRect(GetTransformedTargetBounds(child1.get())),
|
| - ToEnclosingRect(GetTransformedTargetBounds(window1.get())));
|
| + EXPECT_EQ(GetTransformedTargetBounds(child1.get()),
|
| + GetTransformedTargetBounds(window1.get()));
|
| ToggleOverview();
|
| }
|
|
|
| @@ -1504,8 +1600,8 @@ TEST_F(WindowSelectorTest, DisplayOrientationChanged) {
|
| ToggleOverview();
|
| for (ScopedVector<aura::Window>::iterator iter = windows.begin();
|
| iter != windows.end(); ++iter) {
|
| - EXPECT_TRUE(root_window->bounds().Contains(
|
| - ToEnclosingRect(GetTransformedTargetBounds(*iter))));
|
| + EXPECT_TRUE(
|
| + root_window->bounds().Contains(GetTransformedTargetBounds(*iter)));
|
| }
|
|
|
| // Rotate the display, windows should be repositioned to be within the screen
|
| @@ -1514,8 +1610,8 @@ TEST_F(WindowSelectorTest, DisplayOrientationChanged) {
|
| EXPECT_EQ("0,0 200x600", root_window->bounds().ToString());
|
| for (ScopedVector<aura::Window>::iterator iter = windows.begin();
|
| iter != windows.end(); ++iter) {
|
| - EXPECT_TRUE(root_window->bounds().Contains(
|
| - ToEnclosingRect(GetTransformedTargetBounds(*iter))));
|
| + EXPECT_TRUE(
|
| + root_window->bounds().Contains(GetTransformedTargetBounds(*iter)));
|
| }
|
| }
|
|
|
|
|