OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/bind.h" | 5 #include "base/bind.h" |
6 #include "base/logging.h" | 6 #include "base/logging.h" |
7 #include "base/run_loop.h" | 7 #include "base/run_loop.h" |
8 #include "components/mus/common/util.h" | 8 #include "components/mus/common/util.h" |
9 #include "components/mus/public/cpp/tests/window_server_test_base.h" | 9 #include "components/mus/public/cpp/tests/window_server_test_base.h" |
10 #include "components/mus/public/cpp/window_observer.h" | 10 #include "components/mus/public/cpp/window_observer.h" |
11 #include "components/mus/public/cpp/window_tree_connection.h" | 11 #include "components/mus/public/cpp/window_tree_connection.h" |
12 #include "components/mus/public/cpp/window_tree_delegate.h" | 12 #include "components/mus/public/cpp/window_tree_delegate.h" |
13 #include "mojo/application/public/cpp/application_connection.h" | 13 #include "mojo/application/public/cpp/application_connection.h" |
14 #include "mojo/application/public/cpp/application_impl.h" | 14 #include "mojo/application/public/cpp/application_impl.h" |
15 #include "mojo/application/public/cpp/application_test_base.h" | 15 #include "mojo/application/public/cpp/application_test_base.h" |
16 #include "mojo/converters/geometry/geometry_type_converters.h" | 16 #include "mojo/converters/geometry/geometry_type_converters.h" |
17 #include "ui/gfx/geometry/rect.h" | 17 #include "ui/gfx/geometry/rect.h" |
18 #include "ui/mojo/geometry/geometry_util.h" | 18 #include "ui/mojo/geometry/geometry_util.h" |
19 | 19 |
20 namespace mus { | 20 namespace mus { |
21 | 21 |
22 namespace ws { | 22 namespace ws { |
23 | 23 |
24 namespace { | 24 namespace { |
25 | 25 |
| 26 int ValidIndexOf(const Window::Children& windows, Window* window) { |
| 27 Window::Children::const_iterator it = |
| 28 std::find(windows.begin(), windows.end(), window); |
| 29 return (it != windows.end()) ? (it - windows.begin()) : -1; |
| 30 } |
| 31 |
26 class BoundsChangeObserver : public WindowObserver { | 32 class BoundsChangeObserver : public WindowObserver { |
27 public: | 33 public: |
28 explicit BoundsChangeObserver(Window* window) : window_(window) { | 34 explicit BoundsChangeObserver(Window* window) : window_(window) { |
29 window_->AddObserver(this); | 35 window_->AddObserver(this); |
30 } | 36 } |
31 ~BoundsChangeObserver() override { window_->RemoveObserver(this); } | 37 ~BoundsChangeObserver() override { window_->RemoveObserver(this); } |
32 | 38 |
33 private: | 39 private: |
34 // Overridden from WindowObserver: | 40 // Overridden from WindowObserver: |
35 void OnWindowBoundsChanged(Window* window, | 41 void OnWindowBoundsChanged(Window* window, |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 }; | 200 }; |
195 | 201 |
196 // These tests model synchronization of two peer connections to the window | 202 // These tests model synchronization of two peer connections to the window |
197 // manager | 203 // manager |
198 // service, that are given access to some root window. | 204 // service, that are given access to some root window. |
199 | 205 |
200 class WindowServerTest : public WindowServerTestBase { | 206 class WindowServerTest : public WindowServerTestBase { |
201 public: | 207 public: |
202 WindowServerTest() {} | 208 WindowServerTest() {} |
203 | 209 |
| 210 Window* NewVisibleWindow(Window* parent, WindowTreeConnection* connection) { |
| 211 Window* window = connection->NewWindow(); |
| 212 window->SetVisible(true); |
| 213 parent->AddChild(window); |
| 214 return window; |
| 215 } |
| 216 |
204 // Embeds another version of the test app @ window. This runs a run loop until | 217 // Embeds another version of the test app @ window. This runs a run loop until |
205 // a response is received, or a timeout. On success the new WindowServer is | 218 // a response is received, or a timeout. On success the new WindowServer is |
206 // returned. | 219 // returned. |
207 EmbedResult Embed(Window* window) { | 220 EmbedResult Embed(Window* window) { |
208 return Embed(window, mus::mojom::WindowTree::ACCESS_POLICY_DEFAULT); | 221 return Embed(window, mus::mojom::WindowTree::ACCESS_POLICY_DEFAULT); |
209 } | 222 } |
210 | 223 |
211 EmbedResult Embed(Window* window, uint32_t access_policy_bitmask) { | 224 EmbedResult Embed(Window* window, uint32_t access_policy_bitmask) { |
212 DCHECK(!embed_details_); | 225 DCHECK(!embed_details_); |
213 embed_details_.reset(new EmbedDetails); | 226 embed_details_.reset(new EmbedDetails); |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 EXPECT_TRUE(WindowServerTestBase::QuitRunLoop()); | 629 EXPECT_TRUE(WindowServerTestBase::QuitRunLoop()); |
617 } | 630 } |
618 | 631 |
619 Window* window_; | 632 Window* window_; |
620 Window* last_gained_focus_; | 633 Window* last_gained_focus_; |
621 Window* last_lost_focus_; | 634 Window* last_lost_focus_; |
622 | 635 |
623 MOJO_DISALLOW_COPY_AND_ASSIGN(FocusChangeObserver); | 636 MOJO_DISALLOW_COPY_AND_ASSIGN(FocusChangeObserver); |
624 }; | 637 }; |
625 | 638 |
| 639 bool WaitForWindowToHaveFocus(Window* window) { |
| 640 if (window->HasFocus()) |
| 641 return true; |
| 642 FocusChangeObserver observer(window); |
| 643 return WindowServerTestBase::DoRunLoopWithTimeout(); |
| 644 } |
| 645 |
626 } // namespace | 646 } // namespace |
627 | 647 |
628 TEST_F(WindowServerTest, Focus) { | 648 TEST_F(WindowServerTest, Focus) { |
629 Window* window1 = window_manager()->NewWindow(); | 649 Window* window1 = window_manager()->NewWindow(); |
630 window1->SetVisible(true); | 650 window1->SetVisible(true); |
631 window_manager()->GetRoot()->AddChild(window1); | 651 window_manager()->GetRoot()->AddChild(window1); |
632 | 652 |
633 WindowTreeConnection* embedded = Embed(window1).connection; | 653 WindowTreeConnection* embedded = Embed(window1).connection; |
634 ASSERT_NE(nullptr, embedded); | 654 ASSERT_NE(nullptr, embedded); |
635 Window* window11 = embedded->NewWindow(); | 655 Window* window11 = embedded->NewWindow(); |
(...skipping 14 matching lines...) Expand all Loading... |
650 FocusChangeObserver observer(window11); | 670 FocusChangeObserver observer(window11); |
651 window11->SetFocus(); | 671 window11->SetFocus(); |
652 ASSERT_TRUE(DoRunLoopWithTimeout()); | 672 ASSERT_TRUE(DoRunLoopWithTimeout()); |
653 ASSERT_NE(nullptr, observer.last_gained_focus()); | 673 ASSERT_NE(nullptr, observer.last_gained_focus()); |
654 ASSERT_NE(nullptr, observer.last_lost_focus()); | 674 ASSERT_NE(nullptr, observer.last_lost_focus()); |
655 EXPECT_EQ(window11->id(), observer.last_gained_focus()->id()); | 675 EXPECT_EQ(window11->id(), observer.last_gained_focus()->id()); |
656 EXPECT_EQ(embedded->GetRoot()->id(), observer.last_lost_focus()->id()); | 676 EXPECT_EQ(embedded->GetRoot()->id(), observer.last_lost_focus()->id()); |
657 } | 677 } |
658 { | 678 { |
659 // Add an observer on the Window that loses focus, and make sure the | 679 // Add an observer on the Window that loses focus, and make sure the |
660 // observer | 680 // observer sees the right values. |
661 // sees the right values. | |
662 FocusChangeObserver observer(window11); | 681 FocusChangeObserver observer(window11); |
663 embedded->GetRoot()->SetFocus(); | 682 embedded->GetRoot()->SetFocus(); |
664 ASSERT_TRUE(DoRunLoopWithTimeout()); | 683 ASSERT_TRUE(DoRunLoopWithTimeout()); |
665 ASSERT_NE(nullptr, observer.last_gained_focus()); | 684 ASSERT_NE(nullptr, observer.last_gained_focus()); |
666 ASSERT_NE(nullptr, observer.last_lost_focus()); | 685 ASSERT_NE(nullptr, observer.last_lost_focus()); |
667 EXPECT_EQ(window11->id(), observer.last_lost_focus()->id()); | 686 EXPECT_EQ(window11->id(), observer.last_lost_focus()->id()); |
668 EXPECT_EQ(embedded->GetRoot()->id(), observer.last_gained_focus()->id()); | 687 EXPECT_EQ(embedded->GetRoot()->id(), observer.last_gained_focus()->id()); |
669 } | 688 } |
670 } | 689 } |
671 | 690 |
| 691 TEST_F(WindowServerTest, Activation) { |
| 692 Window* parent = |
| 693 NewVisibleWindow(window_manager()->GetRoot(), window_manager()); |
| 694 Window* child1 = NewVisibleWindow(parent, window_manager()); |
| 695 Window* child2 = NewVisibleWindow(parent, window_manager()); |
| 696 Window* child3 = NewVisibleWindow(parent, window_manager()); |
| 697 |
| 698 child1->AddTransientWindow(child3); |
| 699 |
| 700 WindowTreeConnection* embedded1 = Embed(child1).connection; |
| 701 ASSERT_NE(nullptr, embedded1); |
| 702 WindowTreeConnection* embedded2 = Embed(child2).connection; |
| 703 ASSERT_NE(nullptr, embedded2); |
| 704 |
| 705 Window* child11 = NewVisibleWindow(embedded1->GetRoot(), embedded1); |
| 706 Window* child21 = NewVisibleWindow(embedded2->GetRoot(), embedded2); |
| 707 |
| 708 WaitForTreeSizeToMatch(parent, 6); |
| 709 |
| 710 // Allow the child windows to be activated. |
| 711 host()->AddActivationParent(parent->id()); |
| 712 |
| 713 // |child2| and |child3| are stacked about |child1|. |
| 714 EXPECT_GT(ValidIndexOf(parent->children(), child2), |
| 715 ValidIndexOf(parent->children(), child1)); |
| 716 EXPECT_GT(ValidIndexOf(parent->children(), child3), |
| 717 ValidIndexOf(parent->children(), child1)); |
| 718 |
| 719 // Set focus on |child11|. This should activate |child1|, and raise it over |
| 720 // |child2|. But |child3| should still be above |child1| because of |
| 721 // transiency. |
| 722 child11->SetFocus(); |
| 723 ASSERT_TRUE(WaitForWindowToHaveFocus(child11)); |
| 724 ASSERT_TRUE( |
| 725 WaitForWindowToHaveFocus(window_manager()->GetWindowById(child11->id()))); |
| 726 EXPECT_EQ(child11->id(), window_manager()->GetFocusedWindow()->id()); |
| 727 EXPECT_EQ(child11->id(), embedded1->GetFocusedWindow()->id()); |
| 728 EXPECT_EQ(nullptr, embedded2->GetFocusedWindow()); |
| 729 EXPECT_GT(ValidIndexOf(parent->children(), child1), |
| 730 ValidIndexOf(parent->children(), child2)); |
| 731 EXPECT_GT(ValidIndexOf(parent->children(), child3), |
| 732 ValidIndexOf(parent->children(), child1)); |
| 733 |
| 734 // Set focus on |child21|. This should activate |child2|, and raise it over |
| 735 // |child1|. |
| 736 child21->SetFocus(); |
| 737 ASSERT_TRUE(WaitForWindowToHaveFocus(child21)); |
| 738 ASSERT_TRUE( |
| 739 WaitForWindowToHaveFocus(window_manager()->GetWindowById(child21->id()))); |
| 740 EXPECT_EQ(child21->id(), window_manager()->GetFocusedWindow()->id()); |
| 741 EXPECT_EQ(child21->id(), embedded2->GetFocusedWindow()->id()); |
| 742 EXPECT_EQ(nullptr, embedded1->GetFocusedWindow()); |
| 743 EXPECT_GT(ValidIndexOf(parent->children(), child2), |
| 744 ValidIndexOf(parent->children(), child1)); |
| 745 EXPECT_GT(ValidIndexOf(parent->children(), child3), |
| 746 ValidIndexOf(parent->children(), child1)); |
| 747 } |
| 748 |
672 namespace { | 749 namespace { |
673 | 750 |
674 class DestroyedChangedObserver : public WindowObserver { | 751 class DestroyedChangedObserver : public WindowObserver { |
675 public: | 752 public: |
676 DestroyedChangedObserver(WindowServerTestBase* test, | 753 DestroyedChangedObserver(WindowServerTestBase* test, |
677 Window* window, | 754 Window* window, |
678 bool* got_destroy) | 755 bool* got_destroy) |
679 : test_(test), window_(window), got_destroy_(got_destroy) { | 756 : test_(test), window_(window), got_destroy_(got_destroy) { |
680 window_->AddObserver(this); | 757 window_->AddObserver(this); |
681 } | 758 } |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
902 WaitForBoundsToChange(embedded_connection->GetRoot()); | 979 WaitForBoundsToChange(embedded_connection->GetRoot()); |
903 EXPECT_TRUE(gfx::Rect(21, 22, 23, 24) == | 980 EXPECT_TRUE(gfx::Rect(21, 22, 23, 24) == |
904 embedded_connection->GetRoot()->bounds()); | 981 embedded_connection->GetRoot()->bounds()); |
905 EXPECT_TRUE(gfx::Insets(1, 2, 3, 4) == | 982 EXPECT_TRUE(gfx::Insets(1, 2, 3, 4) == |
906 embedded_connection->GetRoot()->client_area()); | 983 embedded_connection->GetRoot()->client_area()); |
907 } | 984 } |
908 | 985 |
909 } // namespace ws | 986 } // namespace ws |
910 | 987 |
911 } // namespace mus | 988 } // namespace mus |
OLD | NEW |