| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/views/widget/sublevel_manager.h" |
| |
| #include <AppKit/AppKit.h> |
| |
| #include <algorithm> |
| #include <memory> |
| #include <string> |
| #include <tuple> |
| #include <utility> |
| |
| #include "base/mac/mac_util.h" |
| #include "build/buildflag.h" |
| #include "ui/views/test/views_test_base.h" |
| #include "ui/views/test/widget_test.h" |
| |
| namespace views { |
| |
| enum WidgetShowType { kShowActive, kShowInactive }; |
| |
| class SublevelManagerMacTest |
| : public ViewsTestBase, |
| public testing::WithParamInterface< |
| std::tuple<WidgetShowType, Widget::InitParams::Activatable>> { |
| public: |
| SublevelManagerMacTest() = default; |
| |
| std::unique_ptr<Widget> CreateChildWidget( |
| Widget* parent, |
| ui::ZOrderLevel level, |
| int sublevel, |
| Widget::InitParams::Activatable activatable) { |
| Widget::InitParams params = CreateParamsForTestWidget(); |
| params.z_order = level; |
| params.sublevel = sublevel; |
| params.activatable = activatable; |
| params.parent = parent->GetNativeView(); |
| return CreateTestWidget(std::move(params)); |
| } |
| |
| // Call Show() or ShowInactive() depending on WidgetShowType. |
| void ShowWidget(const std::unique_ptr<Widget>& widget) { |
| WidgetShowType show_type = std::get<WidgetShowType>(GetParam()); |
| if (show_type == WidgetShowType::kShowActive) { |
| widget->Show(); |
| } else { |
| widget->ShowInactive(); |
| } |
| test::WidgetVisibleWaiter(widget.get()).Wait(); |
| } |
| |
| static std::string PrintTestName( |
| const ::testing::TestParamInfo<SublevelManagerMacTest::ParamType>& info) { |
| std::string test_name; |
| switch (std::get<WidgetShowType>(info.param)) { |
| case WidgetShowType::kShowActive: |
| test_name += "ShowActive"; |
| break; |
| case WidgetShowType::kShowInactive: |
| test_name += "ShowInactive"; |
| break; |
| } |
| test_name += "_"; |
| switch (std::get<Widget::InitParams::Activatable>(info.param)) { |
| case Widget::InitParams::Activatable::kNo: |
| test_name += "NotActivatable"; |
| break; |
| case Widget::InitParams::Activatable::kYes: |
| test_name += "Activatable"; |
| break; |
| default: |
| NOTREACHED(); |
| } |
| return test_name; |
| } |
| }; |
| |
| // Disabled widgets are ignored when its siblings are re-ordered. |
| TEST_P(SublevelManagerMacTest, ExplicitUntrack) { |
| std::unique_ptr<Widget> root = |
| CreateTestWidget(Widget::InitParams::CLIENT_OWNS_WIDGET); |
| std::unique_ptr<Widget> root2 = |
| CreateTestWidget(Widget::InitParams::CLIENT_OWNS_WIDGET); |
| std::array<std::unique_ptr<Widget>, 3> children; |
| |
| ShowWidget(root); |
| ShowWidget(root2); |
| for (size_t i = 0; i < children.size(); i++) { |
| children[i] = CreateChildWidget( |
| root.get(), ui::ZOrderLevel::kNormal, i, |
| std::get<Widget::InitParams::Activatable>(GetParam())); |
| ShowWidget(children[i]); |
| |
| // Disable the second widget. |
| if (i == 1) { |
| children[i]->parent()->GetSublevelManager()->OnWidgetChildRemoved( |
| children[i]->parent(), children[i].get()); |
| } |
| } |
| |
| NSWindow* root_nswindow = root->GetNativeWindow().GetNativeNSWindow(); |
| NSWindow* root2_nswindow = root2->GetNativeWindow().GetNativeNSWindow(); |
| NSWindow* child2_nswindow = |
| children[1]->GetNativeWindow().GetNativeNSWindow(); |
| |
| // Reparent `child2` to root2 at the NSWindow level but not at the Widget |
| // level. |
| [root_nswindow removeChildWindow:child2_nswindow]; |
| [root2_nswindow addChildWindow:child2_nswindow ordered:NSWindowAbove]; |
| |
| children[1]->GetSublevelManager()->EnsureOwnerSublevel(); |
| |
| // The parent of child2 does not change. |
| EXPECT_EQ([child2_nswindow parentWindow], root2_nswindow); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| , |
| SublevelManagerMacTest, |
| ::testing::Combine( |
| ::testing::Values(WidgetShowType::kShowActive, |
| WidgetShowType::kShowInactive), |
| ::testing::Values(Widget::InitParams::Activatable::kNo, |
| Widget::InitParams::Activatable::kYes)), |
| SublevelManagerMacTest::PrintTestName); |
| |
| } // namespace views |