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 <stdint.h> | 5 #include <stdint.h> |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "base/strings/stringprintf.h" |
12 #include "components/mus/common/types.h" | 13 #include "components/mus/common/types.h" |
13 #include "components/mus/common/util.h" | 14 #include "components/mus/common/util.h" |
14 #include "components/mus/public/interfaces/window_tree.mojom.h" | 15 #include "components/mus/public/interfaces/window_tree.mojom.h" |
15 #include "components/mus/surfaces/surfaces_state.h" | 16 #include "components/mus/surfaces/surfaces_state.h" |
16 #include "components/mus/ws/client_connection.h" | 17 #include "components/mus/ws/client_connection.h" |
17 #include "components/mus/ws/connection_manager.h" | 18 #include "components/mus/ws/connection_manager.h" |
18 #include "components/mus/ws/connection_manager_delegate.h" | 19 #include "components/mus/ws/connection_manager_delegate.h" |
19 #include "components/mus/ws/display_manager.h" | 20 #include "components/mus/ws/display_manager.h" |
20 #include "components/mus/ws/display_manager_factory.h" | 21 #include "components/mus/ws/display_manager_factory.h" |
21 #include "components/mus/ws/ids.h" | 22 #include "components/mus/ws/ids.h" |
(...skipping 17 matching lines...) Expand all Loading... |
39 using mus::mojom::Event; | 40 using mus::mojom::Event; |
40 using mus::mojom::EventPtr; | 41 using mus::mojom::EventPtr; |
41 using mus::mojom::LocationData; | 42 using mus::mojom::LocationData; |
42 using mus::mojom::PointerData; | 43 using mus::mojom::PointerData; |
43 using mus::mojom::WindowDataPtr; | 44 using mus::mojom::WindowDataPtr; |
44 | 45 |
45 namespace mus { | 46 namespace mus { |
46 namespace ws { | 47 namespace ws { |
47 namespace { | 48 namespace { |
48 | 49 |
| 50 std::string WindowIdToString(const WindowId& id) { |
| 51 return base::StringPrintf("%d,%d", id.connection_id, id.window_id); |
| 52 } |
| 53 |
| 54 class TestWindowManagerInternal : public mojom::WindowManagerInternal { |
| 55 public: |
| 56 TestWindowManagerInternal() |
| 57 : got_create_top_level_window_(false), change_id_(0u) {} |
| 58 ~TestWindowManagerInternal() override {} |
| 59 |
| 60 bool did_call_create_top_level_window(uint32_t* change_id) { |
| 61 if (!got_create_top_level_window_) |
| 62 return false; |
| 63 |
| 64 got_create_top_level_window_ = false; |
| 65 *change_id = change_id_; |
| 66 return true; |
| 67 } |
| 68 |
| 69 private: |
| 70 // WindowManagerInternal: |
| 71 void WmSetBounds(uint32_t change_id, |
| 72 uint32_t window_id, |
| 73 mojo::RectPtr bounds) override {} |
| 74 void WmSetProperty(uint32_t change_id, |
| 75 uint32_t window_id, |
| 76 const mojo::String& name, |
| 77 mojo::Array<uint8_t> value) override {} |
| 78 void WmCreateTopLevelWindow( |
| 79 uint32_t change_id, |
| 80 mojo::Map<mojo::String, mojo::Array<uint8_t>> properties) override { |
| 81 got_create_top_level_window_ = true; |
| 82 change_id_ = change_id; |
| 83 } |
| 84 |
| 85 bool got_create_top_level_window_; |
| 86 uint32_t change_id_; |
| 87 |
| 88 DISALLOW_COPY_AND_ASSIGN(TestWindowManagerInternal); |
| 89 }; |
| 90 |
49 // ----------------------------------------------------------------------------- | 91 // ----------------------------------------------------------------------------- |
50 | 92 |
51 // WindowTreeClient implementation that logs all calls to a TestChangeTracker. | 93 // WindowTreeClient implementation that logs all calls to a TestChangeTracker. |
52 // TODO(sky): refactor so both this and WindowTreeAppTest share code. | 94 // TODO(sky): refactor so both this and WindowTreeAppTest share code. |
53 class TestWindowTreeClient : public mus::mojom::WindowTreeClient { | 95 class TestWindowTreeClient : public mus::mojom::WindowTreeClient { |
54 public: | 96 public: |
55 TestWindowTreeClient() : binding_(this) {} | 97 TestWindowTreeClient() : binding_(this), record_on_change_completed_(false) {} |
56 ~TestWindowTreeClient() override {} | 98 ~TestWindowTreeClient() override {} |
57 | 99 |
58 TestChangeTracker* tracker() { return &tracker_; } | 100 TestChangeTracker* tracker() { return &tracker_; } |
59 | 101 |
60 void Bind(mojo::InterfaceRequest<mojom::WindowTreeClient> request) { | 102 void Bind(mojo::InterfaceRequest<mojom::WindowTreeClient> request) { |
61 binding_.Bind(std::move(request)); | 103 binding_.Bind(std::move(request)); |
62 } | 104 } |
63 | 105 |
| 106 void set_record_on_change_completed(bool value) { |
| 107 record_on_change_completed_ = value; |
| 108 } |
| 109 |
64 private: | 110 private: |
65 // WindowTreeClient: | 111 // WindowTreeClient: |
66 void OnEmbed(uint16_t connection_id, | 112 void OnEmbed(uint16_t connection_id, |
67 WindowDataPtr root, | 113 WindowDataPtr root, |
68 mus::mojom::WindowTreePtr tree, | 114 mus::mojom::WindowTreePtr tree, |
69 Id focused_window_id, | 115 Id focused_window_id, |
70 uint32_t access_policy) override { | 116 uint32_t access_policy) override { |
71 // TODO(sky): add test coverage of |focused_window_id|. | 117 // TODO(sky): add test coverage of |focused_window_id|. |
72 tracker_.OnEmbed(connection_id, std::move(root)); | 118 tracker_.OnEmbed(connection_id, std::move(root)); |
73 } | 119 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 EventPtr event) override { | 173 EventPtr event) override { |
128 tracker_.OnWindowInputEvent(window, std::move(event)); | 174 tracker_.OnWindowInputEvent(window, std::move(event)); |
129 } | 175 } |
130 void OnWindowFocused(uint32_t focused_window_id) override { | 176 void OnWindowFocused(uint32_t focused_window_id) override { |
131 tracker_.OnWindowFocused(focused_window_id); | 177 tracker_.OnWindowFocused(focused_window_id); |
132 } | 178 } |
133 void OnWindowPredefinedCursorChanged(uint32_t window_id, | 179 void OnWindowPredefinedCursorChanged(uint32_t window_id, |
134 mojom::Cursor cursor_id) override { | 180 mojom::Cursor cursor_id) override { |
135 tracker_.OnWindowPredefinedCursorChanged(window_id, cursor_id); | 181 tracker_.OnWindowPredefinedCursorChanged(window_id, cursor_id); |
136 } | 182 } |
137 void OnChangeCompleted(uint32_t change_id, bool success) override {} | 183 void OnChangeCompleted(uint32_t change_id, bool success) override { |
| 184 if (record_on_change_completed_) |
| 185 tracker_.OnChangeCompleted(change_id, success); |
| 186 } |
138 void RequestClose(uint32_t window_id) override {} | 187 void RequestClose(uint32_t window_id) override {} |
139 void GetWindowManagerInternal( | 188 void GetWindowManagerInternal( |
140 mojo::AssociatedInterfaceRequest<mojom::WindowManagerInternal> internal) | 189 mojo::AssociatedInterfaceRequest<mojom::WindowManagerInternal> internal) |
141 override {} | 190 override {} |
142 | 191 |
143 TestChangeTracker tracker_; | 192 TestChangeTracker tracker_; |
144 | 193 |
145 mojo::Binding<mojom::WindowTreeClient> binding_; | 194 mojo::Binding<mojom::WindowTreeClient> binding_; |
| 195 bool record_on_change_completed_; |
146 | 196 |
147 DISALLOW_COPY_AND_ASSIGN(TestWindowTreeClient); | 197 DISALLOW_COPY_AND_ASSIGN(TestWindowTreeClient); |
148 }; | 198 }; |
149 | 199 |
150 // ----------------------------------------------------------------------------- | 200 // ----------------------------------------------------------------------------- |
151 | 201 |
152 // ClientConnection implementation that vends TestWindowTreeClient. | 202 // ClientConnection implementation that vends TestWindowTreeClient. |
153 class TestClientConnection : public ClientConnection { | 203 class TestClientConnection : public ClientConnection { |
154 public: | 204 public: |
155 explicit TestClientConnection(scoped_ptr<WindowTreeImpl> service_impl) | 205 explicit TestClientConnection(scoped_ptr<WindowTreeImpl> service_impl) |
156 : ClientConnection(std::move(service_impl), &client_) {} | 206 : ClientConnection(std::move(service_impl), &client_), |
| 207 is_paused_(false) {} |
157 | 208 |
158 TestWindowTreeClient* client() { return &client_; } | 209 TestWindowTreeClient* client() { return &client_; } |
159 | 210 |
| 211 bool is_paused() const { return is_paused_; } |
| 212 |
160 // ClientConnection: | 213 // ClientConnection: |
161 mojom::WindowManagerInternal* GetWindowManagerInternal() override { | 214 mojom::WindowManagerInternal* GetWindowManagerInternal() override { |
162 NOTREACHED(); | 215 NOTREACHED(); |
163 return nullptr; | 216 return nullptr; |
164 } | 217 } |
| 218 void SetIncomingMethodCallProcessingPaused(bool paused) override { |
| 219 is_paused_ = paused; |
| 220 } |
165 | 221 |
166 private: | 222 private: |
167 ~TestClientConnection() override {} | 223 ~TestClientConnection() override {} |
168 | 224 |
169 TestWindowTreeClient client_; | 225 TestWindowTreeClient client_; |
| 226 bool is_paused_; |
170 | 227 |
171 DISALLOW_COPY_AND_ASSIGN(TestClientConnection); | 228 DISALLOW_COPY_AND_ASSIGN(TestClientConnection); |
172 }; | 229 }; |
173 | 230 |
174 // ----------------------------------------------------------------------------- | 231 // ----------------------------------------------------------------------------- |
175 | 232 |
176 // Empty implementation of ConnectionManagerDelegate. | 233 // Empty implementation of ConnectionManagerDelegate. |
177 class TestConnectionManagerDelegate : public ConnectionManagerDelegate { | 234 class TestConnectionManagerDelegate : public ConnectionManagerDelegate { |
178 public: | 235 public: |
179 TestConnectionManagerDelegate() : last_connection_(nullptr) {} | 236 TestConnectionManagerDelegate() : last_connection_(nullptr) {} |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 | 407 |
351 TestWindowTreeClient* wm_client() { return wm_client_; } | 408 TestWindowTreeClient* wm_client() { return wm_client_; } |
352 int32_t cursor_id() { return cursor_id_; } | 409 int32_t cursor_id() { return cursor_id_; } |
353 | 410 |
354 TestWindowTreeHostConnection* host_connection() { return host_connection_; } | 411 TestWindowTreeHostConnection* host_connection() { return host_connection_; } |
355 | 412 |
356 void DispatchEventWithoutAck(const ui::Event& event) { | 413 void DispatchEventWithoutAck(const ui::Event& event) { |
357 host_connection()->window_tree_host()->OnEvent(event); | 414 host_connection()->window_tree_host()->OnEvent(event); |
358 } | 415 } |
359 | 416 |
| 417 void set_window_manager_internal(WindowTreeImpl* connection, |
| 418 mojom::WindowManagerInternal* wm_internal) { |
| 419 connection->window_manager_internal_ = wm_internal; |
| 420 } |
| 421 |
360 void AckPreviousEvent() { | 422 void AckPreviousEvent() { |
361 host_connection() | 423 host_connection() |
362 ->window_tree_host() | 424 ->window_tree_host() |
363 ->tree_awaiting_input_ack_->OnWindowInputEventAck(0); | 425 ->tree_awaiting_input_ack_->OnWindowInputEventAck(0); |
364 } | 426 } |
365 | 427 |
366 void DispatchEventAndAckImmediately(const ui::Event& event) { | 428 void DispatchEventAndAckImmediately(const ui::Event& event) { |
367 DispatchEventWithoutAck(event); | 429 DispatchEventWithoutAck(event); |
368 AckPreviousEvent(); | 430 AckPreviousEvent(); |
369 } | 431 } |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
726 DispatchEventWithoutAck(CreateMouseMoveEvent(21, 22)); | 788 DispatchEventWithoutAck(CreateMouseMoveEvent(21, 22)); |
727 ASSERT_EQ(0u, wm_client()->tracker()->changes()->size()); | 789 ASSERT_EQ(0u, wm_client()->tracker()->changes()->size()); |
728 | 790 |
729 // Ack the first event. That should trigger the dispatch of the second event. | 791 // Ack the first event. That should trigger the dispatch of the second event. |
730 AckPreviousEvent(); | 792 AckPreviousEvent(); |
731 ASSERT_EQ(1u, wm_client()->tracker()->changes()->size()); | 793 ASSERT_EQ(1u, wm_client()->tracker()->changes()->size()); |
732 EXPECT_EQ("InputEvent window=0,2 event_action=5", | 794 EXPECT_EQ("InputEvent window=0,2 event_action=5", |
733 ChangesToDescription1(*wm_client()->tracker()->changes())[0]); | 795 ChangesToDescription1(*wm_client()->tracker()->changes())[0]); |
734 } | 796 } |
735 | 797 |
| 798 // Establish connection, call NewTopLevelWindow(), make sure get id, and make |
| 799 // sure client paused. |
| 800 TEST_F(WindowTreeTest, NewTopLevelWindow) { |
| 801 TestWindowManagerInternal wm_internal; |
| 802 set_window_manager_internal(wm_connection(), &wm_internal); |
| 803 TestWindowTreeClient* embed_connection = nullptr; |
| 804 WindowTreeImpl* window_tree_connection = nullptr; |
| 805 ServerWindow* window = nullptr; |
| 806 ASSERT_NO_FATAL_FAILURE( |
| 807 SetupEventTargeting(&embed_connection, &window_tree_connection, &window)); |
| 808 embed_connection->tracker()->changes()->clear(); |
| 809 embed_connection->set_record_on_change_completed(true); |
| 810 |
| 811 // Create a new top level window. |
| 812 mojo::Map<mojo::String, mojo::Array<uint8_t>> properties; |
| 813 properties.mark_non_null(); |
| 814 const uint32_t initial_change_id = 17; |
| 815 const WindowId embed_window_id2_in_child(window_tree_connection->id(), 101); |
| 816 static_cast<mojom::WindowTree*>(window_tree_connection) |
| 817 ->NewTopLevelWindow(initial_change_id, |
| 818 WindowIdToTransportId(embed_window_id2_in_child), |
| 819 std::move(properties)); |
| 820 |
| 821 // The binding should be paused until the wm acks the change. |
| 822 uint32_t wm_change_id = 0u; |
| 823 ASSERT_TRUE(wm_internal.did_call_create_top_level_window(&wm_change_id)); |
| 824 EXPECT_TRUE(last_client_connection()->is_paused()); |
| 825 |
| 826 // Create the window for |embed_window_id2_in_child|. |
| 827 const WindowId embed_window_id2(wm_connection()->id(), 2); |
| 828 EXPECT_TRUE( |
| 829 wm_connection()->NewWindow(embed_window_id2, ServerWindow::Properties())); |
| 830 EXPECT_TRUE(wm_connection()->AddWindow(FirstRoot(wm_connection())->id(), |
| 831 embed_window_id2)); |
| 832 |
| 833 // Ack the change, which should resume the binding. |
| 834 static_cast<mojom::WindowManagerInternalClient*>(wm_connection()) |
| 835 ->OnWmCreatedTopLevelWindow(wm_change_id, |
| 836 WindowIdToTransportId(embed_window_id2)); |
| 837 EXPECT_FALSE(last_client_connection()->is_paused()); |
| 838 EXPECT_EQ("ChangeCompleted id=17 sucess=true", |
| 839 SingleChangeToDescription(*embed_connection->tracker()->changes())); |
| 840 embed_connection->tracker()->changes()->clear(); |
| 841 |
| 842 // Change the visibility of the window from the owner and make sure the |
| 843 // client sees the right id. |
| 844 ServerWindow* embed_window = wm_connection()->GetWindow(embed_window_id2); |
| 845 ASSERT_TRUE(embed_window); |
| 846 EXPECT_FALSE(embed_window->visible()); |
| 847 ASSERT_TRUE(wm_connection()->SetWindowVisibility(embed_window->id(), true)); |
| 848 EXPECT_TRUE(embed_window->visible()); |
| 849 EXPECT_EQ("VisibilityChanged window=" + |
| 850 WindowIdToString(embed_window_id2_in_child) + " visible=true", |
| 851 SingleChangeToDescription(*embed_connection->tracker()->changes())); |
| 852 |
| 853 // Set the visibility from the child using the client assigned id. |
| 854 ASSERT_TRUE(window_tree_connection->SetWindowVisibility( |
| 855 embed_window_id2_in_child, false)); |
| 856 EXPECT_FALSE(embed_window->visible()); |
| 857 } |
| 858 |
736 } // namespace ws | 859 } // namespace ws |
737 } // namespace mus | 860 } // namespace mus |
OLD | NEW |