Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / components / view_manager / view_manager_service_unittest.cc
blob43274bea947bd0ac3f3271c28278d8a1831978f5
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
3 // found in the LICENSE file.
5 #include <string>
6 #include <vector>
8 #include "base/message_loop/message_loop.h"
9 #include "components/view_manager/client_connection.h"
10 #include "components/view_manager/connection_manager.h"
11 #include "components/view_manager/connection_manager_delegate.h"
12 #include "components/view_manager/display_manager.h"
13 #include "components/view_manager/ids.h"
14 #include "components/view_manager/public/cpp/types.h"
15 #include "components/view_manager/public/cpp/util.h"
16 #include "components/view_manager/public/interfaces/view_manager.mojom.h"
17 #include "components/view_manager/server_view.h"
18 #include "components/view_manager/test_change_tracker.h"
19 #include "components/view_manager/view_manager_service_impl.h"
20 #include "components/window_manager/public/interfaces/window_manager.mojom.h"
21 #include "components/window_manager/public/interfaces/window_manager_internal.mojom.h"
22 #include "mojo/converters/geometry/geometry_type_converters.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom.h"
25 #include "ui/gfx/geometry/rect.h"
27 using mojo::Array;
28 using mojo::ERROR_CODE_NONE;
29 using mojo::InterfaceRequest;
30 using mojo::ServiceProvider;
31 using mojo::ServiceProviderPtr;
32 using mojo::String;
33 using mojo::ViewDataPtr;
35 namespace view_manager {
36 namespace {
38 // -----------------------------------------------------------------------------
40 // ViewManagerClient implementation that logs all calls to a TestChangeTracker.
41 // TODO(sky): refactor so both this and ViewManagerServiceAppTest share code.
42 class TestViewManagerClient : public mojo::ViewManagerClient {
43 public:
44 TestViewManagerClient() {}
45 ~TestViewManagerClient() override {}
47 TestChangeTracker* tracker() { return &tracker_; }
49 private:
50 // ViewManagerClient:
51 void OnEmbed(uint16_t connection_id,
52 const String& embedder_url,
53 ViewDataPtr root,
54 mojo::ViewManagerServicePtr view_manager_service,
55 InterfaceRequest<ServiceProvider> services,
56 ServiceProviderPtr exposed_services,
57 mojo::Id focused_view_id) override {
58 // TODO(sky): add test coverage of |focused_view_id|.
59 tracker_.OnEmbed(connection_id, embedder_url, root.Pass());
61 void OnEmbeddedAppDisconnected(uint32_t view) override {
62 tracker_.OnEmbeddedAppDisconnected(view);
64 void OnViewBoundsChanged(uint32_t view,
65 mojo::RectPtr old_bounds,
66 mojo::RectPtr new_bounds) override {
67 tracker_.OnViewBoundsChanged(view, old_bounds.Pass(), new_bounds.Pass());
69 void OnViewViewportMetricsChanged(
70 mojo::ViewportMetricsPtr old_metrics,
71 mojo::ViewportMetricsPtr new_metrics) override {
72 tracker_.OnViewViewportMetricsChanged(old_metrics.Pass(),
73 new_metrics.Pass());
75 void OnViewHierarchyChanged(uint32_t view,
76 uint32_t new_parent,
77 uint32_t old_parent,
78 Array<ViewDataPtr> views) override {
79 tracker_.OnViewHierarchyChanged(view, new_parent, old_parent, views.Pass());
81 void OnViewReordered(uint32_t view_id,
82 uint32_t relative_view_id,
83 mojo::OrderDirection direction) override {
84 tracker_.OnViewReordered(view_id, relative_view_id, direction);
86 void OnViewDeleted(uint32_t view) override { tracker_.OnViewDeleted(view); }
87 void OnViewVisibilityChanged(uint32_t view, bool visible) override {
88 tracker_.OnViewVisibilityChanged(view, visible);
90 void OnViewDrawnStateChanged(uint32_t view, bool drawn) override {
91 tracker_.OnViewDrawnStateChanged(view, drawn);
93 void OnViewSharedPropertyChanged(uint32_t view,
94 const String& name,
95 Array<uint8_t> new_data) override {
96 tracker_.OnViewSharedPropertyChanged(view, name, new_data.Pass());
98 void OnViewInputEvent(uint32_t view,
99 mojo::EventPtr event,
100 const mojo::Callback<void()>& callback) override {
101 tracker_.OnViewInputEvent(view, event.Pass());
103 void OnViewFocused(uint32_t focused_view_id) override {
104 tracker_.OnViewFocused(focused_view_id);
107 TestChangeTracker tracker_;
109 DISALLOW_COPY_AND_ASSIGN(TestViewManagerClient);
112 // -----------------------------------------------------------------------------
114 // ClientConnection implementation that vends TestViewManagerClient.
115 class TestClientConnection : public ClientConnection {
116 public:
117 explicit TestClientConnection(scoped_ptr<ViewManagerServiceImpl> service_impl)
118 : ClientConnection(service_impl.Pass(), &client_) {}
119 ~TestClientConnection() override {}
121 TestViewManagerClient* client() { return &client_; }
123 private:
124 TestViewManagerClient client_;
126 DISALLOW_COPY_AND_ASSIGN(TestClientConnection);
129 // -----------------------------------------------------------------------------
131 // Empty implementation of ConnectionManagerDelegate.
132 class TestConnectionManagerDelegate : public ConnectionManagerDelegate {
133 public:
134 TestConnectionManagerDelegate() : last_connection_(nullptr) {}
135 ~TestConnectionManagerDelegate() override {}
137 TestViewManagerClient* last_client() {
138 return last_connection_ ? last_connection_->client() : nullptr;
141 TestClientConnection* last_connection() { return last_connection_; }
143 private:
144 // ConnectionManagerDelegate:
145 void OnLostConnectionToWindowManager() override {}
147 ClientConnection* CreateClientConnectionForEmbedAtView(
148 ConnectionManager* connection_manager,
149 mojo::InterfaceRequest<mojo::ViewManagerService> service_request,
150 mojo::ConnectionSpecificId creator_id,
151 const std::string& creator_url,
152 const std::string& url,
153 const ViewId& root_id) override {
154 scoped_ptr<ViewManagerServiceImpl> service(new ViewManagerServiceImpl(
155 connection_manager, creator_id, creator_url, url, root_id));
156 last_connection_ = new TestClientConnection(service.Pass());
157 return last_connection_;
159 ClientConnection* CreateClientConnectionForEmbedAtView(
160 ConnectionManager* connection_manager,
161 mojo::InterfaceRequest<mojo::ViewManagerService> service_request,
162 mojo::ConnectionSpecificId creator_id,
163 const std::string& creator_url,
164 const ViewId& root_id,
165 mojo::ViewManagerClientPtr client) override {
166 NOTIMPLEMENTED();
167 return nullptr;
170 TestClientConnection* last_connection_;
172 DISALLOW_COPY_AND_ASSIGN(TestConnectionManagerDelegate);
175 // -----------------------------------------------------------------------------
177 // Empty implementation of DisplayManager.
178 class TestDisplayManager : public DisplayManager {
179 public:
180 TestDisplayManager() {}
181 ~TestDisplayManager() override {}
183 // DisplayManager:
184 void Init(ConnectionManager* connection_manager,
185 mojo::NativeViewportEventDispatcherPtr event_dispatcher) override {}
186 void SchedulePaint(const ServerView* view, const gfx::Rect& bounds) override {
188 void SetViewportSize(const gfx::Size& size) override {}
189 const mojo::ViewportMetrics& GetViewportMetrics() override {
190 return display_metrices_;
193 private:
194 mojo::ViewportMetrics display_metrices_;
196 DISALLOW_COPY_AND_ASSIGN(TestDisplayManager);
199 // -----------------------------------------------------------------------------
201 // Empty implementation of WindowManagerInternal.
202 class TestWindowManagerInternal : public mojo::WindowManagerInternal {
203 public:
204 TestWindowManagerInternal() {}
205 ~TestWindowManagerInternal() override {}
207 // WindowManagerInternal:
208 void SetViewManagerClient(mojo::ScopedMessagePipeHandle) override {}
209 void OnAccelerator(mojo::EventPtr event) override {}
211 private:
212 DISALLOW_COPY_AND_ASSIGN(TestWindowManagerInternal);
215 mojo::EventPtr CreatePointerDownEvent(int x, int y) {
216 mojo::EventPtr event(mojo::Event::New());
217 event->action = mojo::EVENT_TYPE_POINTER_DOWN;
218 event->pointer_data = mojo::PointerData::New();
219 event->pointer_data->pointer_id = 1u;
220 event->pointer_data->x = x;
221 event->pointer_data->y = y;
222 return event.Pass();
225 mojo::EventPtr CreatePointerUpEvent(int x, int y) {
226 mojo::EventPtr event(mojo::Event::New());
227 event->action = mojo::EVENT_TYPE_POINTER_UP;
228 event->pointer_data = mojo::PointerData::New();
229 event->pointer_data->pointer_id = 1u;
230 event->pointer_data->x = x;
231 event->pointer_data->y = y;
232 return event.Pass();
235 } // namespace
237 // -----------------------------------------------------------------------------
239 class ViewManagerServiceTest : public testing::Test {
240 public:
241 ViewManagerServiceTest() : wm_client_(nullptr) {}
242 ~ViewManagerServiceTest() override {}
244 // ViewManagerServiceImpl for the window manager.
245 ViewManagerServiceImpl* wm_connection() {
246 return connection_manager_->GetConnection(1);
249 TestViewManagerClient* last_view_manager_client() {
250 return delegate_.last_client();
253 TestClientConnection* last_client_connection() {
254 return delegate_.last_connection();
257 ConnectionManager* connection_manager() { return connection_manager_.get(); }
259 TestViewManagerClient* wm_client() { return wm_client_; }
261 protected:
262 // testing::Test:
263 void SetUp() override {
264 connection_manager_.reset(new ConnectionManager(
265 &delegate_, scoped_ptr<DisplayManager>(new TestDisplayManager),
266 &wm_internal_));
267 scoped_ptr<ViewManagerServiceImpl> service(new ViewManagerServiceImpl(
268 connection_manager_.get(), kInvalidConnectionId, std::string(),
269 std::string("mojo:window_manager"), RootViewId()));
270 scoped_ptr<TestClientConnection> client_connection(
271 new TestClientConnection(service.Pass()));
272 wm_client_ = client_connection->client();
273 ASSERT_TRUE(wm_client_ != nullptr);
274 connection_manager_->SetWindowManagerClientConnection(
275 client_connection.Pass());
276 ASSERT_TRUE(wm_connection() != nullptr);
277 ASSERT_TRUE(wm_connection()->root() != nullptr);
280 private:
281 // TestViewManagerClient that is used for the WM connection.
282 TestViewManagerClient* wm_client_;
284 TestWindowManagerInternal wm_internal_;
285 TestConnectionManagerDelegate delegate_;
286 scoped_ptr<ConnectionManager> connection_manager_;
287 base::MessageLoop message_loop_;
289 DISALLOW_COPY_AND_ASSIGN(ViewManagerServiceTest);
292 namespace {
294 const ServerView* GetFirstCloned(const ServerView* view) {
295 for (const ServerView* child : view->GetChildren()) {
296 if (child->id() == ClonedViewId())
297 return child;
299 return nullptr;
302 // Provides common setup for animation tests. Creates the following views:
303 // 0,1 (the root, provided by view manager)
304 // 1,1 the second connection is embedded here (view owned by wm_connection()).
305 // 2,1 bounds=1,2 11x22
306 // 2,2 bounds=2,3 6x7
307 // 2,3 bounds=3,4 6x7
308 // CloneAndAnimate() is invoked for 2,2.
309 void SetUpAnimate1(ViewManagerServiceTest* test, ViewId* embed_view_id) {
310 *embed_view_id = ViewId(test->wm_connection()->id(), 1);
311 EXPECT_EQ(ERROR_CODE_NONE, test->wm_connection()->CreateView(*embed_view_id));
312 EXPECT_TRUE(test->wm_connection()->SetViewVisibility(*embed_view_id, true));
313 EXPECT_TRUE(test->wm_connection()->AddView(*(test->wm_connection()->root()),
314 *embed_view_id));
315 test->wm_connection()->EmbedUrl(std::string(), *embed_view_id, nullptr,
316 nullptr);
317 ViewManagerServiceImpl* connection1 =
318 test->connection_manager()->GetConnectionWithRoot(*embed_view_id);
319 ASSERT_TRUE(connection1 != nullptr);
320 ASSERT_NE(connection1, test->wm_connection());
322 const ViewId child1(connection1->id(), 1);
323 EXPECT_EQ(ERROR_CODE_NONE, connection1->CreateView(child1));
324 const ViewId child2(connection1->id(), 2);
325 EXPECT_EQ(ERROR_CODE_NONE, connection1->CreateView(child2));
326 const ViewId child3(connection1->id(), 3);
327 EXPECT_EQ(ERROR_CODE_NONE, connection1->CreateView(child3));
329 ServerView* v1 = connection1->GetView(child1);
330 v1->SetVisible(true);
331 v1->SetBounds(gfx::Rect(1, 2, 11, 22));
332 ServerView* v2 = connection1->GetView(child2);
333 v2->SetVisible(true);
334 v2->SetBounds(gfx::Rect(2, 3, 6, 7));
335 ServerView* v3 = connection1->GetView(child3);
336 v3->SetVisible(true);
337 v3->SetBounds(gfx::Rect(3, 4, 6, 7));
339 EXPECT_TRUE(connection1->AddView(*embed_view_id, child1));
340 EXPECT_TRUE(connection1->AddView(child1, child2));
341 EXPECT_TRUE(connection1->AddView(child2, child3));
343 TestViewManagerClient* connection1_client = test->last_view_manager_client();
344 connection1_client->tracker()->changes()->clear();
345 test->wm_client()->tracker()->changes()->clear();
346 EXPECT_TRUE(test->connection_manager()->CloneAndAnimate(child2));
347 EXPECT_TRUE(connection1_client->tracker()->changes()->empty());
348 EXPECT_TRUE(test->wm_client()->tracker()->changes()->empty());
350 // We cloned v2. The cloned view ends up as a sibling of it.
351 const ServerView* cloned_view = GetFirstCloned(connection1->GetView(child1));
352 ASSERT_TRUE(cloned_view);
353 // |cloned_view| should have one and only one cloned child (corresponds to
354 // |child3|).
355 ASSERT_EQ(1u, cloned_view->GetChildren().size());
356 EXPECT_TRUE(cloned_view->GetChildren()[0]->id() == ClonedViewId());
358 // Cloned views should match the bounds of the view they were cloned from.
359 EXPECT_EQ(v2->bounds(), cloned_view->bounds());
360 EXPECT_EQ(v3->bounds(), cloned_view->GetChildren()[0]->bounds());
362 // Cloned views are owned by the ConnectionManager and shouldn't be returned
363 // from ViewManagerServiceImpl::GetView.
364 EXPECT_TRUE(connection1->GetView(ClonedViewId()) == nullptr);
365 EXPECT_TRUE(test->wm_connection()->GetView(ClonedViewId()) == nullptr);
368 } // namespace
370 // Verifies ViewManagerService::GetViewTree() doesn't return cloned views.
371 TEST_F(ViewManagerServiceTest, ConnectionsCantSeeClonedViews) {
372 ViewId embed_view_id;
373 EXPECT_NO_FATAL_FAILURE(SetUpAnimate1(this, &embed_view_id));
375 ViewManagerServiceImpl* connection1 =
376 connection_manager()->GetConnectionWithRoot(embed_view_id);
378 const ViewId child1(connection1->id(), 1);
379 const ViewId child2(connection1->id(), 2);
380 const ViewId child3(connection1->id(), 3);
382 // Verify the root doesn't see any cloned views.
383 std::vector<const ServerView*> views(
384 wm_connection()->GetViewTree(*wm_connection()->root()));
385 ASSERT_EQ(5u, views.size());
386 ASSERT_TRUE(views[0]->id() == *wm_connection()->root());
387 ASSERT_TRUE(views[1]->id() == embed_view_id);
388 ASSERT_TRUE(views[2]->id() == child1);
389 ASSERT_TRUE(views[3]->id() == child2);
390 ASSERT_TRUE(views[4]->id() == child3);
392 // Verify connection1 doesn't see any cloned views.
393 std::vector<const ServerView*> v1_views(
394 connection1->GetViewTree(embed_view_id));
395 ASSERT_EQ(4u, v1_views.size());
396 ASSERT_TRUE(v1_views[0]->id() == embed_view_id);
397 ASSERT_TRUE(v1_views[1]->id() == child1);
398 ASSERT_TRUE(v1_views[2]->id() == child2);
399 ASSERT_TRUE(v1_views[3]->id() == child3);
402 TEST_F(ViewManagerServiceTest, ClonedViewsPromotedOnConnectionClose) {
403 ViewId embed_view_id;
404 EXPECT_NO_FATAL_FAILURE(SetUpAnimate1(this, &embed_view_id));
406 // Destroy connection1, which should force the cloned view to become a child
407 // of where it was embedded (the embedded view still exists).
408 connection_manager()->OnConnectionError(last_client_connection());
410 ServerView* embed_view = wm_connection()->GetView(embed_view_id);
411 ASSERT_TRUE(embed_view != nullptr);
412 const ServerView* cloned_view = GetFirstCloned(embed_view);
413 ASSERT_TRUE(cloned_view);
414 ASSERT_EQ(1u, cloned_view->GetChildren().size());
415 EXPECT_TRUE(cloned_view->GetChildren()[0]->id() == ClonedViewId());
417 // Because the cloned view changed parents its bounds should have changed.
418 EXPECT_EQ(gfx::Rect(3, 5, 6, 7), cloned_view->bounds());
419 // The bounds of the cloned child should not have changed though.
420 EXPECT_EQ(gfx::Rect(3, 4, 6, 7), cloned_view->GetChildren()[0]->bounds());
423 TEST_F(ViewManagerServiceTest, ClonedViewsPromotedOnHide) {
424 ViewId embed_view_id;
425 EXPECT_NO_FATAL_FAILURE(SetUpAnimate1(this, &embed_view_id));
427 ViewManagerServiceImpl* connection1 =
428 connection_manager()->GetConnectionWithRoot(embed_view_id);
430 // Hide the parent of the cloned view, which should force the cloned view to
431 // become a sibling of the parent.
432 const ServerView* view_to_hide =
433 connection1->GetView(ViewId(connection1->id(), 1));
434 ASSERT_TRUE(connection1->SetViewVisibility(view_to_hide->id(), false));
436 const ServerView* cloned_view = GetFirstCloned(view_to_hide->parent());
437 ASSERT_TRUE(cloned_view);
438 ASSERT_EQ(1u, cloned_view->GetChildren().size());
439 EXPECT_TRUE(cloned_view->GetChildren()[0]->id() == ClonedViewId());
440 EXPECT_EQ(2u, cloned_view->parent()->GetChildren().size());
441 EXPECT_TRUE(cloned_view->parent()->GetChildren()[1] == cloned_view);
444 // Clone and animate on a tree with more depth. Basically that of
445 // SetUpAnimate1() but cloning 2,1.
446 TEST_F(ViewManagerServiceTest, CloneAndAnimateLargerDepth) {
447 const ViewId embed_view_id(wm_connection()->id(), 1);
448 EXPECT_EQ(ERROR_CODE_NONE, wm_connection()->CreateView(embed_view_id));
449 EXPECT_TRUE(wm_connection()->SetViewVisibility(embed_view_id, true));
450 EXPECT_TRUE(
451 wm_connection()->AddView(*(wm_connection()->root()), embed_view_id));
452 wm_connection()->EmbedUrl(std::string(), embed_view_id, nullptr, nullptr);
453 ViewManagerServiceImpl* connection1 =
454 connection_manager()->GetConnectionWithRoot(embed_view_id);
455 ASSERT_TRUE(connection1 != nullptr);
456 ASSERT_NE(connection1, wm_connection());
458 const ViewId child1(connection1->id(), 1);
459 EXPECT_EQ(ERROR_CODE_NONE, connection1->CreateView(child1));
460 const ViewId child2(connection1->id(), 2);
461 EXPECT_EQ(ERROR_CODE_NONE, connection1->CreateView(child2));
462 const ViewId child3(connection1->id(), 3);
463 EXPECT_EQ(ERROR_CODE_NONE, connection1->CreateView(child3));
465 ServerView* v1 = connection1->GetView(child1);
466 v1->SetVisible(true);
467 connection1->GetView(child2)->SetVisible(true);
468 connection1->GetView(child3)->SetVisible(true);
470 EXPECT_TRUE(connection1->AddView(embed_view_id, child1));
471 EXPECT_TRUE(connection1->AddView(child1, child2));
472 EXPECT_TRUE(connection1->AddView(child2, child3));
474 TestViewManagerClient* connection1_client = last_view_manager_client();
475 connection1_client->tracker()->changes()->clear();
476 wm_client()->tracker()->changes()->clear();
477 EXPECT_TRUE(connection_manager()->CloneAndAnimate(child1));
478 EXPECT_TRUE(connection1_client->tracker()->changes()->empty());
479 EXPECT_TRUE(wm_client()->tracker()->changes()->empty());
481 // We cloned v1. The cloned view ends up as a sibling of it.
482 const ServerView* cloned_view = GetFirstCloned(v1->parent());
483 ASSERT_TRUE(cloned_view);
484 // |cloned_view| should have a child and its child should have a child.
485 ASSERT_EQ(1u, cloned_view->GetChildren().size());
486 const ServerView* cloned_view_child = cloned_view->GetChildren()[0];
487 EXPECT_EQ(1u, cloned_view_child->GetChildren().size());
488 EXPECT_TRUE(cloned_view_child->id() == ClonedViewId());
491 // Verifies focus correctly changes on pointer events.
492 TEST_F(ViewManagerServiceTest, FocusOnPointer) {
493 const ViewId embed_view_id(wm_connection()->id(), 1);
494 EXPECT_EQ(ERROR_CODE_NONE, wm_connection()->CreateView(embed_view_id));
495 EXPECT_TRUE(wm_connection()->SetViewVisibility(embed_view_id, true));
496 EXPECT_TRUE(
497 wm_connection()->AddView(*(wm_connection()->root()), embed_view_id));
498 connection_manager()->root()->SetBounds(gfx::Rect(0, 0, 100, 100));
499 wm_connection()->EmbedUrl(std::string(), embed_view_id, nullptr, nullptr);
500 ViewManagerServiceImpl* connection1 =
501 connection_manager()->GetConnectionWithRoot(embed_view_id);
502 ASSERT_TRUE(connection1 != nullptr);
503 ASSERT_NE(connection1, wm_connection());
505 connection_manager()
506 ->GetView(embed_view_id)
507 ->SetBounds(gfx::Rect(0, 0, 50, 50));
509 const ViewId child1(connection1->id(), 1);
510 EXPECT_EQ(ERROR_CODE_NONE, connection1->CreateView(child1));
511 EXPECT_TRUE(connection1->AddView(embed_view_id, child1));
512 ServerView* v1 = connection1->GetView(child1);
513 v1->SetVisible(true);
514 v1->SetBounds(gfx::Rect(20, 20, 20, 20));
516 TestViewManagerClient* connection1_client = last_view_manager_client();
517 connection1_client->tracker()->changes()->clear();
518 wm_client()->tracker()->changes()->clear();
520 connection_manager()->ProcessEvent(CreatePointerDownEvent(21, 22));
521 // Focus should go to child1. This results in notifying both the window
522 // manager and client connection being notified.
523 EXPECT_EQ(v1, connection_manager()->GetFocusedView());
524 ASSERT_GE(wm_client()->tracker()->changes()->size(), 1u);
525 EXPECT_EQ("Focused id=2,1",
526 ChangesToDescription1(*wm_client()->tracker()->changes())[0]);
527 ASSERT_GE(connection1_client->tracker()->changes()->size(), 1u);
528 EXPECT_EQ(
529 "Focused id=2,1",
530 ChangesToDescription1(*connection1_client->tracker()->changes())[0]);
532 connection_manager()->ProcessEvent(CreatePointerUpEvent(21, 22));
533 wm_client()->tracker()->changes()->clear();
534 connection1_client->tracker()->changes()->clear();
536 // Press outside of the embedded view. Focus should go to the root. Notice
537 // the client1 doesn't see who has focus as the focused view (root) isn't
538 // visible to it.
539 connection_manager()->ProcessEvent(CreatePointerDownEvent(61, 22));
540 EXPECT_EQ(connection_manager()->root(),
541 connection_manager()->GetFocusedView());
542 ASSERT_GE(wm_client()->tracker()->changes()->size(), 1u);
543 EXPECT_EQ("Focused id=0,1",
544 ChangesToDescription1(*wm_client()->tracker()->changes())[0]);
545 ASSERT_GE(connection1_client->tracker()->changes()->size(), 1u);
546 EXPECT_EQ(
547 "Focused id=null",
548 ChangesToDescription1(*connection1_client->tracker()->changes())[0]);
550 connection_manager()->ProcessEvent(CreatePointerUpEvent(21, 22));
551 wm_client()->tracker()->changes()->clear();
552 connection1_client->tracker()->changes()->clear();
554 // Press in the same location. Should not get a focus change event (only input
555 // event).
556 connection_manager()->ProcessEvent(CreatePointerDownEvent(61, 22));
557 EXPECT_EQ(connection_manager()->root(),
558 connection_manager()->GetFocusedView());
559 ASSERT_EQ(wm_client()->tracker()->changes()->size(), 1u);
560 EXPECT_EQ("InputEvent view=0,1 event_action=4",
561 ChangesToDescription1(*wm_client()->tracker()->changes())[0]);
562 EXPECT_TRUE(connection1_client->tracker()->changes()->empty());
566 } // namespace view_manager