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 "services/ui/ws/window_tree.h" | 5 #include "services/ui/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> |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 ->capture_window(); | 90 ->capture_window(); |
91 } | 91 } |
92 | 92 |
93 mojom::EventMatcherPtr CreateEventMatcher(ui::mojom::EventType type) { | 93 mojom::EventMatcherPtr CreateEventMatcher(ui::mojom::EventType type) { |
94 mojom::EventMatcherPtr matcher = mojom::EventMatcher::New(); | 94 mojom::EventMatcherPtr matcher = mojom::EventMatcher::New(); |
95 matcher->type_matcher = mojom::EventTypeMatcher::New(); | 95 matcher->type_matcher = mojom::EventTypeMatcher::New(); |
96 matcher->type_matcher->type = type; | 96 matcher->type_matcher->type = type; |
97 return matcher; | 97 return matcher; |
98 } | 98 } |
99 | 99 |
| 100 class TestMoveLoopWindowManager : public TestWindowManager { |
| 101 public: |
| 102 TestMoveLoopWindowManager(WindowTree* tree) : tree_(tree) {} |
| 103 ~TestMoveLoopWindowManager() override {} |
| 104 |
| 105 void WmPerformMoveLoop(uint32_t change_id, |
| 106 uint32_t window_id, |
| 107 mojom::MoveLoopSource source, |
| 108 const gfx::Point& cursor_location) override { |
| 109 static_cast<mojom::WindowManagerClient*>(tree_)->WmResponse( |
| 110 change_id, true); |
| 111 } |
| 112 |
| 113 private: |
| 114 WindowTree* tree_; |
| 115 |
| 116 DISALLOW_COPY_AND_ASSIGN(TestMoveLoopWindowManager); |
| 117 }; |
| 118 |
100 } // namespace | 119 } // namespace |
101 | 120 |
102 // ----------------------------------------------------------------------------- | 121 // ----------------------------------------------------------------------------- |
103 | 122 |
104 class WindowTreeTest : public testing::Test { | 123 class WindowTreeTest : public testing::Test { |
105 public: | 124 public: |
106 WindowTreeTest() {} | 125 WindowTreeTest() {} |
107 ~WindowTreeTest() override {} | 126 ~WindowTreeTest() override {} |
108 | 127 |
109 ui::mojom::Cursor cursor_id() { | 128 ui::mojom::Cursor cursor_id() { |
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1005 EXPECT_EQ(owning_tree, wm_state_test_api.tree_awaiting_input_ack()); | 1024 EXPECT_EQ(owning_tree, wm_state_test_api.tree_awaiting_input_ack()); |
1006 AckPreviousEvent(); | 1025 AckPreviousEvent(); |
1007 | 1026 |
1008 // Set capture from the embedded client and make sure it gets the event. | 1027 // Set capture from the embedded client and make sure it gets the event. |
1009 ASSERT_TRUE( | 1028 ASSERT_TRUE( |
1010 embed_tree->SetCapture(ClientWindowIdForWindow(embed_tree, window))); | 1029 embed_tree->SetCapture(ClientWindowIdForWindow(embed_tree, window))); |
1011 DispatchEventWithoutAck(CreateMouseMoveEvent(22, 23)); | 1030 DispatchEventWithoutAck(CreateMouseMoveEvent(22, 23)); |
1012 EXPECT_EQ(embed_tree, wm_state_test_api.tree_awaiting_input_ack()); | 1031 EXPECT_EQ(embed_tree, wm_state_test_api.tree_awaiting_input_ack()); |
1013 } | 1032 } |
1014 | 1033 |
| 1034 TEST_F(WindowTreeTest, ValidMoveLoopWithWM) { |
| 1035 TestWindowManager wm_internal; |
| 1036 set_window_manager_internal(wm_tree(), &wm_internal); |
| 1037 |
| 1038 TestWindowTreeBinding* child_binding; |
| 1039 WindowTree* child_tree = CreateNewTree(wm_tree()->user_id(), &child_binding); |
| 1040 child_binding->client()->tracker()->changes()->clear(); |
| 1041 child_binding->client()->set_record_on_change_completed(true); |
| 1042 |
| 1043 // Create a new top level window. |
| 1044 mojo::Map<mojo::String, mojo::Array<uint8_t>> properties; |
| 1045 const uint32_t initial_change_id = 17; |
| 1046 // Explicitly use an id that does not contain the client id. |
| 1047 const ClientWindowId embed_window_id2_in_child(45 << 16 | 27); |
| 1048 static_cast<mojom::WindowTree*>(child_tree) |
| 1049 ->NewTopLevelWindow(initial_change_id, embed_window_id2_in_child.id, |
| 1050 std::move(properties)); |
| 1051 |
| 1052 // The binding should be paused until the wm acks the change. |
| 1053 uint32_t wm_change_id = 0u; |
| 1054 ASSERT_TRUE(wm_internal.did_call_create_top_level_window(&wm_change_id)); |
| 1055 EXPECT_TRUE(child_binding->is_paused()); |
| 1056 |
| 1057 // Create the window for |embed_window_id2_in_child|. |
| 1058 const ClientWindowId embed_window_id2 = BuildClientWindowId(wm_tree(), 2); |
| 1059 EXPECT_TRUE( |
| 1060 wm_tree()->NewWindow(embed_window_id2, ServerWindow::Properties())); |
| 1061 EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id2, true)); |
| 1062 EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id2)); |
| 1063 |
| 1064 // Ack the change, which should resume the binding. |
| 1065 child_binding->client()->tracker()->changes()->clear(); |
| 1066 static_cast<mojom::WindowManagerClient*>(wm_tree()) |
| 1067 ->OnWmCreatedTopLevelWindow(wm_change_id, embed_window_id2.id); |
| 1068 EXPECT_FALSE(child_binding->is_paused()); |
| 1069 |
| 1070 // The child_tree is the one that has to make this call; the |
| 1071 const uint32_t change_id = 7; |
| 1072 static_cast<mojom::WindowTree*>(child_tree) |
| 1073 ->PerformWindowMove(change_id, embed_window_id2_in_child.id, |
| 1074 mojom::MoveLoopSource::MOUSE, gfx::Point(0, 0)); |
| 1075 |
| 1076 EXPECT_TRUE(wm_internal.on_perform_move_loop_called()); |
| 1077 } |
| 1078 |
| 1079 TEST_F(WindowTreeTest, MoveLoopAckOKByWM) { |
| 1080 TestMoveLoopWindowManager wm_internal(wm_tree()); |
| 1081 set_window_manager_internal(wm_tree(), &wm_internal); |
| 1082 |
| 1083 TestWindowTreeBinding* child_binding; |
| 1084 WindowTree* child_tree = CreateNewTree(wm_tree()->user_id(), &child_binding); |
| 1085 child_binding->client()->tracker()->changes()->clear(); |
| 1086 child_binding->client()->set_record_on_change_completed(true); |
| 1087 |
| 1088 // Create a new top level window. |
| 1089 mojo::Map<mojo::String, mojo::Array<uint8_t>> properties; |
| 1090 const uint32_t initial_change_id = 17; |
| 1091 // Explicitly use an id that does not contain the client id. |
| 1092 const ClientWindowId embed_window_id2_in_child(45 << 16 | 27); |
| 1093 static_cast<mojom::WindowTree*>(child_tree) |
| 1094 ->NewTopLevelWindow(initial_change_id, embed_window_id2_in_child.id, |
| 1095 std::move(properties)); |
| 1096 |
| 1097 // The binding should be paused until the wm acks the change. |
| 1098 uint32_t wm_change_id = 0u; |
| 1099 ASSERT_TRUE(wm_internal.did_call_create_top_level_window(&wm_change_id)); |
| 1100 EXPECT_TRUE(child_binding->is_paused()); |
| 1101 |
| 1102 // Create the window for |embed_window_id2_in_child|. |
| 1103 const ClientWindowId embed_window_id2 = BuildClientWindowId(wm_tree(), 2); |
| 1104 EXPECT_TRUE( |
| 1105 wm_tree()->NewWindow(embed_window_id2, ServerWindow::Properties())); |
| 1106 EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id2, true)); |
| 1107 EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id2)); |
| 1108 |
| 1109 // Ack the change, which should resume the binding. |
| 1110 child_binding->client()->tracker()->changes()->clear(); |
| 1111 static_cast<mojom::WindowManagerClient*>(wm_tree()) |
| 1112 ->OnWmCreatedTopLevelWindow(wm_change_id, embed_window_id2.id); |
| 1113 EXPECT_FALSE(child_binding->is_paused()); |
| 1114 |
| 1115 // The child_tree is the one that has to make this call; the |
| 1116 const uint32_t change_id = 7; |
| 1117 child_binding->client()->tracker()->changes()->clear(); |
| 1118 static_cast<mojom::WindowTree*>(child_tree) |
| 1119 ->PerformWindowMove(change_id, embed_window_id2_in_child.id, |
| 1120 mojom::MoveLoopSource::MOUSE, gfx::Point(0, 0)); |
| 1121 |
| 1122 EXPECT_EQ("ChangeCompleted id=7 sucess=true", |
| 1123 SingleChangeToDescription( |
| 1124 *child_binding->client()->tracker()->changes())); |
| 1125 } |
| 1126 |
| 1127 TEST_F(WindowTreeTest, WindowManagerCantMoveLoop) { |
| 1128 TestWindowManager wm_internal; |
| 1129 set_window_manager_internal(wm_tree(), &wm_internal); |
| 1130 |
| 1131 TestWindowTreeBinding* child_binding; |
| 1132 WindowTree* child_tree = CreateNewTree(wm_tree()->user_id(), &child_binding); |
| 1133 child_binding->client()->tracker()->changes()->clear(); |
| 1134 child_binding->client()->set_record_on_change_completed(true); |
| 1135 |
| 1136 // Create a new top level window. |
| 1137 mojo::Map<mojo::String, mojo::Array<uint8_t>> properties; |
| 1138 const uint32_t initial_change_id = 17; |
| 1139 // Explicitly use an id that does not contain the client id. |
| 1140 const ClientWindowId embed_window_id2_in_child(45 << 16 | 27); |
| 1141 static_cast<mojom::WindowTree*>(child_tree) |
| 1142 ->NewTopLevelWindow(initial_change_id, embed_window_id2_in_child.id, |
| 1143 std::move(properties)); |
| 1144 |
| 1145 // The binding should be paused until the wm acks the change. |
| 1146 uint32_t wm_change_id = 0u; |
| 1147 ASSERT_TRUE(wm_internal.did_call_create_top_level_window(&wm_change_id)); |
| 1148 EXPECT_TRUE(child_binding->is_paused()); |
| 1149 |
| 1150 // Create the window for |embed_window_id2_in_child|. |
| 1151 const ClientWindowId embed_window_id2 = BuildClientWindowId(wm_tree(), 2); |
| 1152 EXPECT_TRUE( |
| 1153 wm_tree()->NewWindow(embed_window_id2, ServerWindow::Properties())); |
| 1154 EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id2, true)); |
| 1155 EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id2)); |
| 1156 |
| 1157 // Ack the change, which should resume the binding. |
| 1158 child_binding->client()->tracker()->changes()->clear(); |
| 1159 static_cast<mojom::WindowManagerClient*>(wm_tree()) |
| 1160 ->OnWmCreatedTopLevelWindow(wm_change_id, embed_window_id2.id); |
| 1161 EXPECT_FALSE(child_binding->is_paused()); |
| 1162 |
| 1163 // Making this call from the wm_tree() must be invalid. |
| 1164 const uint32_t change_id = 7; |
| 1165 static_cast<mojom::WindowTree*>(wm_tree())->PerformWindowMove( |
| 1166 change_id, embed_window_id2.id, mojom::MoveLoopSource::MOUSE, |
| 1167 gfx::Point(0, 0)); |
| 1168 |
| 1169 EXPECT_FALSE(wm_internal.on_perform_move_loop_called()); |
| 1170 } |
| 1171 |
| 1172 TEST_F(WindowTreeTest, RevertWindowBoundsOnMoveLoopFailure) { |
| 1173 TestWindowManager wm_internal; |
| 1174 set_window_manager_internal(wm_tree(), &wm_internal); |
| 1175 |
| 1176 TestWindowTreeBinding* child_binding; |
| 1177 WindowTree* child_tree = CreateNewTree(wm_tree()->user_id(), &child_binding); |
| 1178 child_binding->client()->tracker()->changes()->clear(); |
| 1179 child_binding->client()->set_record_on_change_completed(true); |
| 1180 |
| 1181 // Create a new top level window. |
| 1182 mojo::Map<mojo::String, mojo::Array<uint8_t>> properties; |
| 1183 const uint32_t initial_change_id = 17; |
| 1184 // Explicitly use an id that does not contain the client id. |
| 1185 const ClientWindowId embed_window_id2_in_child(45 << 16 | 27); |
| 1186 static_cast<mojom::WindowTree*>(child_tree) |
| 1187 ->NewTopLevelWindow(initial_change_id, embed_window_id2_in_child.id, |
| 1188 std::move(properties)); |
| 1189 |
| 1190 // The binding should be paused until the wm acks the change. |
| 1191 uint32_t wm_change_id = 0u; |
| 1192 ASSERT_TRUE(wm_internal.did_call_create_top_level_window(&wm_change_id)); |
| 1193 EXPECT_TRUE(child_binding->is_paused()); |
| 1194 |
| 1195 // Create the window for |embed_window_id2_in_child|. |
| 1196 const ClientWindowId embed_window_id2 = BuildClientWindowId(wm_tree(), 2); |
| 1197 EXPECT_TRUE( |
| 1198 wm_tree()->NewWindow(embed_window_id2, ServerWindow::Properties())); |
| 1199 EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id2, true)); |
| 1200 EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id2)); |
| 1201 |
| 1202 // Ack the change, which should resume the binding. |
| 1203 child_binding->client()->tracker()->changes()->clear(); |
| 1204 static_cast<mojom::WindowManagerClient*>(wm_tree()) |
| 1205 ->OnWmCreatedTopLevelWindow(wm_change_id, embed_window_id2.id); |
| 1206 EXPECT_FALSE(child_binding->is_paused()); |
| 1207 |
| 1208 // The child_tree is the one that has to make this call; the |
| 1209 const uint32_t change_id = 7; |
| 1210 static_cast<mojom::WindowTree*>(child_tree) |
| 1211 ->PerformWindowMove(change_id, embed_window_id2_in_child.id, |
| 1212 mojom::MoveLoopSource::MOUSE, gfx::Point(0, 0)); |
| 1213 |
| 1214 ServerWindow* server_window = |
| 1215 wm_tree()->GetWindowByClientId(embed_window_id2); |
| 1216 gfx::Rect old_bounds = server_window->bounds(); |
| 1217 server_window->SetBounds(gfx::Rect(10, 10, 20, 20)); |
| 1218 |
| 1219 // Cancel the move loop. |
| 1220 const uint32_t kFirstWMChange = 1; |
| 1221 static_cast<mojom::WindowManagerClient*>(wm_tree())->WmResponse( |
| 1222 kFirstWMChange, false); |
| 1223 |
| 1224 // Canceling the move loop should have reverted the bounds. |
| 1225 EXPECT_EQ(old_bounds, server_window->bounds()); |
| 1226 } |
| 1227 |
| 1228 TEST_F(WindowTreeTest, InvalidMoveLoopStillAcksAttempt) { |
| 1229 // We send a PerformWindowMove for an invalid window. We expect to receive a |
| 1230 // non-success OnMoveLoopCompleted() event. |
| 1231 TestWindowTreeClient* embed_client = nullptr; |
| 1232 WindowTree* tree = nullptr; |
| 1233 ServerWindow* window = nullptr; |
| 1234 EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); |
| 1235 |
| 1236 embed_client->set_record_on_change_completed(true); |
| 1237 |
| 1238 const uint32_t kChangeId = 8; |
| 1239 const Id kInvalidWindowId = 1234567890; |
| 1240 static_cast<mojom::WindowTree*>(tree)->PerformWindowMove( |
| 1241 kChangeId, kInvalidWindowId, mojom::MoveLoopSource::MOUSE, |
| 1242 gfx::Point(0, 0)); |
| 1243 |
| 1244 EXPECT_EQ("ChangeCompleted id=8 sucess=false", |
| 1245 SingleChangeToDescription(*embed_client->tracker()->changes())); |
| 1246 } |
| 1247 |
1015 } // namespace test | 1248 } // namespace test |
1016 } // namespace ws | 1249 } // namespace ws |
1017 } // namespace ui | 1250 } // namespace ui |
OLD | NEW |