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 "components/mus/ws/window_tree.h" | 5 #include "components/mus/ws/window_tree.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/macros.h" | 12 #include "base/macros.h" |
13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
15 #include "components/mus/common/types.h" | 15 #include "components/mus/common/types.h" |
16 #include "components/mus/common/util.h" | 16 #include "components/mus/common/util.h" |
| 17 #include "components/mus/public/cpp/lib/in_flight_change.h" |
17 #include "components/mus/public/interfaces/window_tree.mojom.h" | 18 #include "components/mus/public/interfaces/window_tree.mojom.h" |
18 #include "components/mus/surfaces/surfaces_state.h" | 19 #include "components/mus/surfaces/surfaces_state.h" |
19 #include "components/mus/ws/default_access_policy.h" | 20 #include "components/mus/ws/default_access_policy.h" |
20 #include "components/mus/ws/display_binding.h" | 21 #include "components/mus/ws/display_binding.h" |
21 #include "components/mus/ws/ids.h" | 22 #include "components/mus/ws/ids.h" |
22 #include "components/mus/ws/platform_display.h" | 23 #include "components/mus/ws/platform_display.h" |
23 #include "components/mus/ws/platform_display_factory.h" | 24 #include "components/mus/ws/platform_display_factory.h" |
24 #include "components/mus/ws/platform_display_init_params.h" | 25 #include "components/mus/ws/platform_display_init_params.h" |
25 #include "components/mus/ws/server_window.h" | 26 #include "components/mus/ws/server_window.h" |
26 #include "components/mus/ws/server_window_surface_manager_test_api.h" | 27 #include "components/mus/ws/server_window_surface_manager_test_api.h" |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 return display->GetActiveWindowManagerState()->capture_window(); | 88 return display->GetActiveWindowManagerState()->capture_window(); |
88 } | 89 } |
89 | 90 |
90 mojom::EventMatcherPtr CreateEventMatcher(ui::mojom::EventType type) { | 91 mojom::EventMatcherPtr CreateEventMatcher(ui::mojom::EventType type) { |
91 mojom::EventMatcherPtr matcher = mojom::EventMatcher::New(); | 92 mojom::EventMatcherPtr matcher = mojom::EventMatcher::New(); |
92 matcher->type_matcher = mojom::EventTypeMatcher::New(); | 93 matcher->type_matcher = mojom::EventTypeMatcher::New(); |
93 matcher->type_matcher->type = type; | 94 matcher->type_matcher->type = type; |
94 return matcher; | 95 return matcher; |
95 } | 96 } |
96 | 97 |
| 98 class TestMoveLoopWindowManager : public TestWindowManager { |
| 99 public: |
| 100 TestMoveLoopWindowManager(WindowTree* tree) : tree_(tree) {} |
| 101 ~TestMoveLoopWindowManager() override {} |
| 102 |
| 103 void WmPerformMoveLoop(uint32_t change_id, |
| 104 uint32_t window_id, |
| 105 const gfx::Point& cursor_location) override { |
| 106 static_cast<mojom::WindowManagerClient*>(tree_)->OnWmMoveLoopCompleted( |
| 107 change_id, window_id, true); |
| 108 } |
| 109 |
| 110 private: |
| 111 WindowTree* tree_; |
| 112 |
| 113 DISALLOW_COPY_AND_ASSIGN(TestMoveLoopWindowManager); |
| 114 }; |
| 115 |
97 } // namespace | 116 } // namespace |
98 | 117 |
99 // ----------------------------------------------------------------------------- | 118 // ----------------------------------------------------------------------------- |
100 | 119 |
101 class WindowTreeTest : public testing::Test { | 120 class WindowTreeTest : public testing::Test { |
102 public: | 121 public: |
103 WindowTreeTest() {} | 122 WindowTreeTest() {} |
104 ~WindowTreeTest() override {} | 123 ~WindowTreeTest() override {} |
105 | 124 |
106 mus::mojom::Cursor cursor_id() { | 125 mus::mojom::Cursor cursor_id() { |
(...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1001 EXPECT_EQ(owning_tree, wm_state_test_api.tree_awaiting_input_ack()); | 1020 EXPECT_EQ(owning_tree, wm_state_test_api.tree_awaiting_input_ack()); |
1002 AckPreviousEvent(); | 1021 AckPreviousEvent(); |
1003 | 1022 |
1004 // Set capture from the embedded client and make sure it gets the event. | 1023 // Set capture from the embedded client and make sure it gets the event. |
1005 ASSERT_TRUE( | 1024 ASSERT_TRUE( |
1006 embed_tree->SetCapture(ClientWindowIdForWindow(embed_tree, window))); | 1025 embed_tree->SetCapture(ClientWindowIdForWindow(embed_tree, window))); |
1007 DispatchEventWithoutAck(CreateMouseMoveEvent(22, 23)); | 1026 DispatchEventWithoutAck(CreateMouseMoveEvent(22, 23)); |
1008 EXPECT_EQ(embed_tree, wm_state_test_api.tree_awaiting_input_ack()); | 1027 EXPECT_EQ(embed_tree, wm_state_test_api.tree_awaiting_input_ack()); |
1009 } | 1028 } |
1010 | 1029 |
| 1030 TEST_F(WindowTreeTest, ValidMoveLoopWithWM) { |
| 1031 TestWindowManager wm_internal; |
| 1032 set_window_manager_internal(wm_tree(), &wm_internal); |
| 1033 |
| 1034 TestWindowTreeBinding* child_binding; |
| 1035 WindowTree* child_tree = CreateNewTree(wm_tree()->user_id(), &child_binding); |
| 1036 child_binding->client()->tracker()->changes()->clear(); |
| 1037 child_binding->client()->set_record_on_change_completed(true); |
| 1038 |
| 1039 // Create a new top level window. |
| 1040 mojo::Map<mojo::String, mojo::Array<uint8_t>> properties; |
| 1041 const uint32_t initial_change_id = 17; |
| 1042 // Explicitly use an id that does not contain the client id. |
| 1043 const ClientWindowId embed_window_id2_in_child(45 << 16 | 27); |
| 1044 static_cast<mojom::WindowTree*>(child_tree) |
| 1045 ->NewTopLevelWindow(initial_change_id, embed_window_id2_in_child.id, |
| 1046 std::move(properties)); |
| 1047 |
| 1048 // The binding should be paused until the wm acks the change. |
| 1049 uint32_t wm_change_id = 0u; |
| 1050 ASSERT_TRUE(wm_internal.did_call_create_top_level_window(&wm_change_id)); |
| 1051 EXPECT_TRUE(child_binding->is_paused()); |
| 1052 |
| 1053 // Create the window for |embed_window_id2_in_child|. |
| 1054 const ClientWindowId embed_window_id2 = BuildClientWindowId(wm_tree(), 2); |
| 1055 EXPECT_TRUE( |
| 1056 wm_tree()->NewWindow(embed_window_id2, ServerWindow::Properties())); |
| 1057 EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id2, true)); |
| 1058 EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id2)); |
| 1059 |
| 1060 // Ack the change, which should resume the binding. |
| 1061 child_binding->client()->tracker()->changes()->clear(); |
| 1062 static_cast<mojom::WindowManagerClient*>(wm_tree()) |
| 1063 ->OnWmCreatedTopLevelWindow(wm_change_id, embed_window_id2.id); |
| 1064 EXPECT_FALSE(child_binding->is_paused()); |
| 1065 |
| 1066 // The child_tree is the one that has to make this call; the |
| 1067 const uint32_t change_id = 7; |
| 1068 static_cast<mojom::WindowTree*>(child_tree) |
| 1069 ->PerformWindowMove(change_id, embed_window_id2_in_child.id, |
| 1070 gfx::Point(0, 0)); |
| 1071 |
| 1072 EXPECT_TRUE(wm_internal.on_perform_move_loop_called()); |
| 1073 } |
| 1074 |
| 1075 TEST_F(WindowTreeTest, MoveLoopAckOKByWM) { |
| 1076 TestMoveLoopWindowManager wm_internal(wm_tree()); |
| 1077 set_window_manager_internal(wm_tree(), &wm_internal); |
| 1078 |
| 1079 TestWindowTreeBinding* child_binding; |
| 1080 WindowTree* child_tree = CreateNewTree(wm_tree()->user_id(), &child_binding); |
| 1081 child_binding->client()->tracker()->changes()->clear(); |
| 1082 child_binding->client()->set_record_on_change_completed(true); |
| 1083 |
| 1084 // Create a new top level window. |
| 1085 mojo::Map<mojo::String, mojo::Array<uint8_t>> properties; |
| 1086 const uint32_t initial_change_id = 17; |
| 1087 // Explicitly use an id that does not contain the client id. |
| 1088 const ClientWindowId embed_window_id2_in_child(45 << 16 | 27); |
| 1089 static_cast<mojom::WindowTree*>(child_tree) |
| 1090 ->NewTopLevelWindow(initial_change_id, embed_window_id2_in_child.id, |
| 1091 std::move(properties)); |
| 1092 |
| 1093 // The binding should be paused until the wm acks the change. |
| 1094 uint32_t wm_change_id = 0u; |
| 1095 ASSERT_TRUE(wm_internal.did_call_create_top_level_window(&wm_change_id)); |
| 1096 EXPECT_TRUE(child_binding->is_paused()); |
| 1097 |
| 1098 // Create the window for |embed_window_id2_in_child|. |
| 1099 const ClientWindowId embed_window_id2 = BuildClientWindowId(wm_tree(), 2); |
| 1100 EXPECT_TRUE( |
| 1101 wm_tree()->NewWindow(embed_window_id2, ServerWindow::Properties())); |
| 1102 EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id2, true)); |
| 1103 EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id2)); |
| 1104 |
| 1105 // Ack the change, which should resume the binding. |
| 1106 child_binding->client()->tracker()->changes()->clear(); |
| 1107 static_cast<mojom::WindowManagerClient*>(wm_tree()) |
| 1108 ->OnWmCreatedTopLevelWindow(wm_change_id, embed_window_id2.id); |
| 1109 EXPECT_FALSE(child_binding->is_paused()); |
| 1110 |
| 1111 // The child_tree is the one that has to make this call; the |
| 1112 const uint32_t change_id = 7; |
| 1113 child_binding->client()->tracker()->changes()->clear(); |
| 1114 static_cast<mojom::WindowTree*>(child_tree) |
| 1115 ->PerformWindowMove(change_id, embed_window_id2_in_child.id, |
| 1116 gfx::Point(0, 0)); |
| 1117 |
| 1118 EXPECT_EQ("ChangeCompleted id=7 sucess=true", |
| 1119 SingleChangeToDescription( |
| 1120 *child_binding->client()->tracker()->changes())); |
| 1121 } |
| 1122 |
| 1123 TEST_F(WindowTreeTest, WindowManagerCantMoveLoop) { |
| 1124 TestWindowManager wm_internal; |
| 1125 set_window_manager_internal(wm_tree(), &wm_internal); |
| 1126 |
| 1127 TestWindowTreeBinding* child_binding; |
| 1128 WindowTree* child_tree = CreateNewTree(wm_tree()->user_id(), &child_binding); |
| 1129 child_binding->client()->tracker()->changes()->clear(); |
| 1130 child_binding->client()->set_record_on_change_completed(true); |
| 1131 |
| 1132 // Create a new top level window. |
| 1133 mojo::Map<mojo::String, mojo::Array<uint8_t>> properties; |
| 1134 const uint32_t initial_change_id = 17; |
| 1135 // Explicitly use an id that does not contain the client id. |
| 1136 const ClientWindowId embed_window_id2_in_child(45 << 16 | 27); |
| 1137 static_cast<mojom::WindowTree*>(child_tree) |
| 1138 ->NewTopLevelWindow(initial_change_id, embed_window_id2_in_child.id, |
| 1139 std::move(properties)); |
| 1140 |
| 1141 // The binding should be paused until the wm acks the change. |
| 1142 uint32_t wm_change_id = 0u; |
| 1143 ASSERT_TRUE(wm_internal.did_call_create_top_level_window(&wm_change_id)); |
| 1144 EXPECT_TRUE(child_binding->is_paused()); |
| 1145 |
| 1146 // Create the window for |embed_window_id2_in_child|. |
| 1147 const ClientWindowId embed_window_id2 = BuildClientWindowId(wm_tree(), 2); |
| 1148 EXPECT_TRUE( |
| 1149 wm_tree()->NewWindow(embed_window_id2, ServerWindow::Properties())); |
| 1150 EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id2, true)); |
| 1151 EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id2)); |
| 1152 |
| 1153 // Ack the change, which should resume the binding. |
| 1154 child_binding->client()->tracker()->changes()->clear(); |
| 1155 static_cast<mojom::WindowManagerClient*>(wm_tree()) |
| 1156 ->OnWmCreatedTopLevelWindow(wm_change_id, embed_window_id2.id); |
| 1157 EXPECT_FALSE(child_binding->is_paused()); |
| 1158 |
| 1159 // Making this call from the wm_tree() must be invalid. |
| 1160 const uint32_t change_id = 7; |
| 1161 static_cast<mojom::WindowTree*>(wm_tree())->PerformWindowMove( |
| 1162 change_id, embed_window_id2.id, gfx::Point(0, 0)); |
| 1163 |
| 1164 EXPECT_FALSE(wm_internal.on_perform_move_loop_called()); |
| 1165 } |
| 1166 |
| 1167 TEST_F(WindowTreeTest, InvalidMoveLoopStillAcksAttempt) { |
| 1168 // We send a PerformWindowMove for an invalid window. We expect to receive a |
| 1169 // non-success OnMoveLoopCompleted() event. |
| 1170 TestWindowTreeClient* embed_client = nullptr; |
| 1171 WindowTree* tree = nullptr; |
| 1172 ServerWindow* window = nullptr; |
| 1173 EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); |
| 1174 |
| 1175 embed_client->set_record_on_change_completed(true); |
| 1176 |
| 1177 const uint32_t kChangeId = 8; |
| 1178 const Id kInvalidWindowId = 1234567890; |
| 1179 static_cast<mojom::WindowTree*>(tree)->PerformWindowMove( |
| 1180 kChangeId, kInvalidWindowId, gfx::Point(0, 0)); |
| 1181 |
| 1182 EXPECT_EQ("ChangeCompleted id=8 sucess=false", |
| 1183 SingleChangeToDescription(*embed_client->tracker()->changes())); |
| 1184 } |
| 1185 |
1011 } // namespace test | 1186 } // namespace test |
1012 } // namespace ws | 1187 } // namespace ws |
1013 } // namespace mus | 1188 } // namespace mus |
OLD | NEW |