| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <algorithm> | 5 #include <algorithm> |
| 6 #include <memory> |
| 6 #include <set> | 7 #include <set> |
| 7 | 8 |
| 8 #include "base/bind.h" | 9 #include "base/bind.h" |
| 9 #include "base/macros.h" | 10 #include "base/macros.h" |
| 10 #include "base/memory/scoped_ptr.h" | |
| 11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 14 #include "build/build_config.h" | 14 #include "build/build_config.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 #include "ui/base/hit_test.h" | 16 #include "ui/base/hit_test.h" |
| 17 #include "ui/compositor/layer_animation_observer.h" | 17 #include "ui/compositor/layer_animation_observer.h" |
| 18 #include "ui/compositor/scoped_animation_duration_scale_mode.h" | 18 #include "ui/compositor/scoped_animation_duration_scale_mode.h" |
| 19 #include "ui/compositor/scoped_layer_animation_settings.h" | 19 #include "ui/compositor/scoped_layer_animation_settings.h" |
| 20 #include "ui/events/event_utils.h" | 20 #include "ui/events/event_utils.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 | 54 |
| 55 // TODO(tdanderson): This utility function is used in different unittest | 55 // TODO(tdanderson): This utility function is used in different unittest |
| 56 // files. Move to a common location to avoid | 56 // files. Move to a common location to avoid |
| 57 // repeated code. | 57 // repeated code. |
| 58 gfx::Point ConvertPointFromWidgetToView(View* view, const gfx::Point& p) { | 58 gfx::Point ConvertPointFromWidgetToView(View* view, const gfx::Point& p) { |
| 59 gfx::Point tmp(p); | 59 gfx::Point tmp(p); |
| 60 View::ConvertPointToTarget(view->GetWidget()->GetRootView(), view, &tmp); | 60 View::ConvertPointToTarget(view->GetWidget()->GetRootView(), view, &tmp); |
| 61 return tmp; | 61 return tmp; |
| 62 } | 62 } |
| 63 | 63 |
| 64 // This class can be used as a deleter for scoped_ptr<Widget> | 64 // This class can be used as a deleter for std::unique_ptr<Widget> |
| 65 // to call function Widget::CloseNow automatically. | 65 // to call function Widget::CloseNow automatically. |
| 66 struct WidgetCloser { | 66 struct WidgetCloser { |
| 67 inline void operator()(Widget* widget) const { widget->CloseNow(); } | 67 inline void operator()(Widget* widget) const { widget->CloseNow(); } |
| 68 }; | 68 }; |
| 69 | 69 |
| 70 using WidgetAutoclosePtr = scoped_ptr<Widget, WidgetCloser>; | 70 using WidgetAutoclosePtr = std::unique_ptr<Widget, WidgetCloser>; |
| 71 | 71 |
| 72 } // namespace | 72 } // namespace |
| 73 | 73 |
| 74 // A view that keeps track of the events it receives, and consumes all scroll | 74 // A view that keeps track of the events it receives, and consumes all scroll |
| 75 // gesture events and ui::ET_SCROLL events. | 75 // gesture events and ui::ET_SCROLL events. |
| 76 class ScrollableEventCountView : public EventCountView { | 76 class ScrollableEventCountView : public EventCountView { |
| 77 public: | 77 public: |
| 78 ScrollableEventCountView() {} | 78 ScrollableEventCountView() {} |
| 79 ~ScrollableEventCountView() override {} | 79 ~ScrollableEventCountView() override {} |
| 80 | 80 |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 DISALLOW_COPY_AND_ASSIGN(OwnershipTestWidget); | 372 DISALLOW_COPY_AND_ASSIGN(OwnershipTestWidget); |
| 373 }; | 373 }; |
| 374 | 374 |
| 375 // TODO(sky): add coverage of ownership for the desktop variants. | 375 // TODO(sky): add coverage of ownership for the desktop variants. |
| 376 | 376 |
| 377 // Widget owns its NativeWidget, part 1: NativeWidget is a platform-native | 377 // Widget owns its NativeWidget, part 1: NativeWidget is a platform-native |
| 378 // widget. | 378 // widget. |
| 379 TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsPlatformNativeWidget) { | 379 TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsPlatformNativeWidget) { |
| 380 OwnershipTestState state; | 380 OwnershipTestState state; |
| 381 | 381 |
| 382 scoped_ptr<Widget> widget(new OwnershipTestWidget(&state)); | 382 std::unique_ptr<Widget> widget(new OwnershipTestWidget(&state)); |
| 383 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); | 383 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); |
| 384 params.native_widget = CreatePlatformNativeWidgetImpl( | 384 params.native_widget = CreatePlatformNativeWidgetImpl( |
| 385 params, widget.get(), kStubCapture, &state.native_widget_deleted); | 385 params, widget.get(), kStubCapture, &state.native_widget_deleted); |
| 386 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 386 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 387 widget->Init(params); | 387 widget->Init(params); |
| 388 | 388 |
| 389 // Now delete the Widget, which should delete the NativeWidget. | 389 // Now delete the Widget, which should delete the NativeWidget. |
| 390 widget.reset(); | 390 widget.reset(); |
| 391 | 391 |
| 392 EXPECT_TRUE(state.widget_deleted); | 392 EXPECT_TRUE(state.widget_deleted); |
| 393 EXPECT_TRUE(state.native_widget_deleted); | 393 EXPECT_TRUE(state.native_widget_deleted); |
| 394 | 394 |
| 395 // TODO(beng): write test for this ownership scenario and the NativeWidget | 395 // TODO(beng): write test for this ownership scenario and the NativeWidget |
| 396 // being deleted out from under the Widget. | 396 // being deleted out from under the Widget. |
| 397 } | 397 } |
| 398 | 398 |
| 399 // Widget owns its NativeWidget, part 2: NativeWidget is a NativeWidget. | 399 // Widget owns its NativeWidget, part 2: NativeWidget is a NativeWidget. |
| 400 TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsViewsNativeWidget) { | 400 TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsViewsNativeWidget) { |
| 401 OwnershipTestState state; | 401 OwnershipTestState state; |
| 402 | 402 |
| 403 scoped_ptr<Widget> widget(new OwnershipTestWidget(&state)); | 403 std::unique_ptr<Widget> widget(new OwnershipTestWidget(&state)); |
| 404 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); | 404 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); |
| 405 params.native_widget = CreatePlatformNativeWidgetImpl( | 405 params.native_widget = CreatePlatformNativeWidgetImpl( |
| 406 params, widget.get(), kStubCapture, &state.native_widget_deleted); | 406 params, widget.get(), kStubCapture, &state.native_widget_deleted); |
| 407 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 407 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 408 widget->Init(params); | 408 widget->Init(params); |
| 409 | 409 |
| 410 // Now delete the Widget, which should delete the NativeWidget. | 410 // Now delete the Widget, which should delete the NativeWidget. |
| 411 widget.reset(); | 411 widget.reset(); |
| 412 | 412 |
| 413 EXPECT_TRUE(state.widget_deleted); | 413 EXPECT_TRUE(state.widget_deleted); |
| 414 EXPECT_TRUE(state.native_widget_deleted); | 414 EXPECT_TRUE(state.native_widget_deleted); |
| 415 | 415 |
| 416 // TODO(beng): write test for this ownership scenario and the NativeWidget | 416 // TODO(beng): write test for this ownership scenario and the NativeWidget |
| 417 // being deleted out from under the Widget. | 417 // being deleted out from under the Widget. |
| 418 } | 418 } |
| 419 | 419 |
| 420 // Widget owns its NativeWidget, part 3: NativeWidget is a NativeWidget, | 420 // Widget owns its NativeWidget, part 3: NativeWidget is a NativeWidget, |
| 421 // destroy the parent view. | 421 // destroy the parent view. |
| 422 TEST_F(WidgetOwnershipTest, | 422 TEST_F(WidgetOwnershipTest, |
| 423 Ownership_WidgetOwnsViewsNativeWidget_DestroyParentView) { | 423 Ownership_WidgetOwnsViewsNativeWidget_DestroyParentView) { |
| 424 OwnershipTestState state; | 424 OwnershipTestState state; |
| 425 | 425 |
| 426 Widget* toplevel = CreateTopLevelPlatformWidget(); | 426 Widget* toplevel = CreateTopLevelPlatformWidget(); |
| 427 | 427 |
| 428 scoped_ptr<Widget> widget(new OwnershipTestWidget(&state)); | 428 std::unique_ptr<Widget> widget(new OwnershipTestWidget(&state)); |
| 429 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); | 429 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); |
| 430 params.parent = toplevel->GetNativeView(); | 430 params.parent = toplevel->GetNativeView(); |
| 431 params.native_widget = CreatePlatformNativeWidgetImpl( | 431 params.native_widget = CreatePlatformNativeWidgetImpl( |
| 432 params, widget.get(), kStubCapture, &state.native_widget_deleted); | 432 params, widget.get(), kStubCapture, &state.native_widget_deleted); |
| 433 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 433 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 434 widget->Init(params); | 434 widget->Init(params); |
| 435 | 435 |
| 436 // Now close the toplevel, which deletes the view hierarchy. | 436 // Now close the toplevel, which deletes the view hierarchy. |
| 437 toplevel->CloseNow(); | 437 toplevel->CloseNow(); |
| 438 | 438 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 EXPECT_TRUE(state.native_widget_deleted); | 564 EXPECT_TRUE(state.native_widget_deleted); |
| 565 } | 565 } |
| 566 | 566 |
| 567 // Widget owns its NativeWidget and has a WidgetDelegateView as its contents. | 567 // Widget owns its NativeWidget and has a WidgetDelegateView as its contents. |
| 568 TEST_F(WidgetOwnershipTest, | 568 TEST_F(WidgetOwnershipTest, |
| 569 Ownership_WidgetOwnsNativeWidgetWithWithWidgetDelegateView) { | 569 Ownership_WidgetOwnsNativeWidgetWithWithWidgetDelegateView) { |
| 570 OwnershipTestState state; | 570 OwnershipTestState state; |
| 571 | 571 |
| 572 WidgetDelegateView* delegate_view = new WidgetDelegateView; | 572 WidgetDelegateView* delegate_view = new WidgetDelegateView; |
| 573 | 573 |
| 574 scoped_ptr<Widget> widget(new OwnershipTestWidget(&state)); | 574 std::unique_ptr<Widget> widget(new OwnershipTestWidget(&state)); |
| 575 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); | 575 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); |
| 576 params.native_widget = CreatePlatformNativeWidgetImpl( | 576 params.native_widget = CreatePlatformNativeWidgetImpl( |
| 577 params, widget.get(), kStubCapture, &state.native_widget_deleted); | 577 params, widget.get(), kStubCapture, &state.native_widget_deleted); |
| 578 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 578 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 579 params.delegate = delegate_view; | 579 params.delegate = delegate_view; |
| 580 widget->Init(params); | 580 widget->Init(params); |
| 581 widget->SetContentsView(delegate_view); | 581 widget->SetContentsView(delegate_view); |
| 582 | 582 |
| 583 // Now delete the Widget. There should be no crash or use-after-free. | 583 // Now delete the Widget. There should be no crash or use-after-free. |
| 584 widget.reset(); | 584 widget.reset(); |
| (...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1527 EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_END)); | 1527 EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_END)); |
| 1528 } | 1528 } |
| 1529 } | 1529 } |
| 1530 | 1530 |
| 1531 // Tests that event-handlers installed on the RootView get triggered correctly. | 1531 // Tests that event-handlers installed on the RootView get triggered correctly. |
| 1532 // TODO(tdanderson): Clean up this test as part of crbug.com/355680. | 1532 // TODO(tdanderson): Clean up this test as part of crbug.com/355680. |
| 1533 TEST_F(WidgetTest, EventHandlersOnRootView) { | 1533 TEST_F(WidgetTest, EventHandlersOnRootView) { |
| 1534 WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); | 1534 WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); |
| 1535 View* root_view = widget->GetRootView(); | 1535 View* root_view = widget->GetRootView(); |
| 1536 | 1536 |
| 1537 scoped_ptr<EventCountView> view(new EventCountView()); | 1537 std::unique_ptr<EventCountView> view(new EventCountView()); |
| 1538 view->set_owned_by_client(); | 1538 view->set_owned_by_client(); |
| 1539 view->SetBounds(0, 0, 20, 20); | 1539 view->SetBounds(0, 0, 20, 20); |
| 1540 root_view->AddChildView(view.get()); | 1540 root_view->AddChildView(view.get()); |
| 1541 | 1541 |
| 1542 EventCountHandler h1; | 1542 EventCountHandler h1; |
| 1543 root_view->AddPreTargetHandler(&h1); | 1543 root_view->AddPreTargetHandler(&h1); |
| 1544 | 1544 |
| 1545 EventCountHandler h2; | 1545 EventCountHandler h2; |
| 1546 root_view->AddPostTargetHandler(&h2); | 1546 root_view->AddPostTargetHandler(&h2); |
| 1547 | 1547 |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1717 widget->Show(); | 1717 widget->Show(); |
| 1718 widget->SetSize(gfx::Size(300, 300)); | 1718 widget->SetSize(gfx::Size(300, 300)); |
| 1719 | 1719 |
| 1720 EventCountView* event_count_view = new EventCountView(); | 1720 EventCountView* event_count_view = new EventCountView(); |
| 1721 event_count_view->SetBounds(0, 0, 300, 300); | 1721 event_count_view->SetBounds(0, 0, 300, 300); |
| 1722 widget->GetRootView()->AddChildView(event_count_view); | 1722 widget->GetRootView()->AddChildView(event_count_view); |
| 1723 | 1723 |
| 1724 MousePressEventConsumer consumer; | 1724 MousePressEventConsumer consumer; |
| 1725 event_count_view->AddPostTargetHandler(&consumer); | 1725 event_count_view->AddPostTargetHandler(&consumer); |
| 1726 | 1726 |
| 1727 scoped_ptr<ui::test::EventGenerator> generator(new ui::test::EventGenerator( | 1727 std::unique_ptr<ui::test::EventGenerator> generator( |
| 1728 IsMus() ? widget->GetNativeWindow() : GetContext(), | 1728 new ui::test::EventGenerator( |
| 1729 widget->GetNativeWindow())); | 1729 IsMus() ? widget->GetNativeWindow() : GetContext(), |
| 1730 widget->GetNativeWindow())); |
| 1730 generator->PressTouch(); | 1731 generator->PressTouch(); |
| 1731 generator->ClickLeftButton(); | 1732 generator->ClickLeftButton(); |
| 1732 | 1733 |
| 1733 EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED)); | 1734 EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED)); |
| 1734 EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_RELEASED)); | 1735 EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_RELEASED)); |
| 1735 | 1736 |
| 1736 // For mus it's important we destroy the widget before the EventGenerator. | 1737 // For mus it's important we destroy the widget before the EventGenerator. |
| 1737 widget->CloseNow(); | 1738 widget->CloseNow(); |
| 1738 } | 1739 } |
| 1739 | 1740 |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1989 EXPECT_TRUE(destroyed); | 1990 EXPECT_TRUE(destroyed); |
| 1990 // Close() should destroy the widget. If not we'll cleanup to avoid leaks. | 1991 // Close() should destroy the widget. If not we'll cleanup to avoid leaks. |
| 1991 if (!destroyed) { | 1992 if (!destroyed) { |
| 1992 widget->Detach(); | 1993 widget->Detach(); |
| 1993 widget->CloseNow(); | 1994 widget->CloseNow(); |
| 1994 } | 1995 } |
| 1995 } | 1996 } |
| 1996 | 1997 |
| 1997 // Tests that killing a widget while animating it does not crash. | 1998 // Tests that killing a widget while animating it does not crash. |
| 1998 TEST_F(WidgetTest, CloseWidgetWhileAnimating) { | 1999 TEST_F(WidgetTest, CloseWidgetWhileAnimating) { |
| 1999 scoped_ptr<Widget> widget(new Widget); | 2000 std::unique_ptr<Widget> widget(new Widget); |
| 2000 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); | 2001 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); |
| 2001 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 2002 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 2002 params.bounds = gfx::Rect(50, 50, 250, 250); | 2003 params.bounds = gfx::Rect(50, 50, 250, 250); |
| 2003 widget->Init(params); | 2004 widget->Init(params); |
| 2004 AnimationEndObserver animation_observer; | 2005 AnimationEndObserver animation_observer; |
| 2005 WidgetBoundsObserver widget_observer; | 2006 WidgetBoundsObserver widget_observer; |
| 2006 gfx::Rect bounds(100, 100, 50, 50); | 2007 gfx::Rect bounds(100, 100, 50, 50); |
| 2007 { | 2008 { |
| 2008 // Normal animations for tests have ZERO_DURATION, make sure we are actually | 2009 // Normal animations for tests have ZERO_DURATION, make sure we are actually |
| 2009 // animating the movement. | 2010 // animating the movement. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2051 base::RunLoop().RunUntilIdle(); | 2052 base::RunLoop().RunUntilIdle(); |
| 2052 // Broken on Linux. See http://crbug.com/515379. | 2053 // Broken on Linux. See http://crbug.com/515379. |
| 2053 #if !defined(OS_LINUX) || defined(OS_CHROMEOS) | 2054 #if !defined(OS_LINUX) || defined(OS_CHROMEOS) |
| 2054 EXPECT_EQ(screen_rect, observer.bounds()); | 2055 EXPECT_EQ(screen_rect, observer.bounds()); |
| 2055 #endif | 2056 #endif |
| 2056 } | 2057 } |
| 2057 | 2058 |
| 2058 // Tests that we do not crash when a Widget is destroyed by going out of | 2059 // Tests that we do not crash when a Widget is destroyed by going out of |
| 2059 // scope (as opposed to being explicitly deleted by its NativeWidget). | 2060 // scope (as opposed to being explicitly deleted by its NativeWidget). |
| 2060 TEST_F(WidgetTest, NoCrashOnWidgetDelete) { | 2061 TEST_F(WidgetTest, NoCrashOnWidgetDelete) { |
| 2061 scoped_ptr<Widget> widget(new Widget); | 2062 std::unique_ptr<Widget> widget(new Widget); |
| 2062 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); | 2063 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); |
| 2063 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 2064 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 2064 widget->Init(params); | 2065 widget->Init(params); |
| 2065 } | 2066 } |
| 2066 | 2067 |
| 2067 // Tests that we do not crash when a Widget is destroyed before it finishes | 2068 // Tests that we do not crash when a Widget is destroyed before it finishes |
| 2068 // processing of pending input events in the message loop. | 2069 // processing of pending input events in the message loop. |
| 2069 TEST_F(WidgetTest, NoCrashOnWidgetDeleteWithPendingEvents) { | 2070 TEST_F(WidgetTest, NoCrashOnWidgetDeleteWithPendingEvents) { |
| 2070 scoped_ptr<Widget> widget(new Widget); | 2071 std::unique_ptr<Widget> widget(new Widget); |
| 2071 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); | 2072 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); |
| 2072 params.bounds = gfx::Rect(0, 0, 200, 200); | 2073 params.bounds = gfx::Rect(0, 0, 200, 200); |
| 2073 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 2074 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 2074 widget->Init(params); | 2075 widget->Init(params); |
| 2075 widget->Show(); | 2076 widget->Show(); |
| 2076 | 2077 |
| 2077 ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow()); | 2078 ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow()); |
| 2078 generator.MoveMouseTo(10, 10); | 2079 generator.MoveMouseTo(10, 10); |
| 2079 | 2080 |
| 2080 // No touch on desktop Mac. Tracked in http://crbug.com/445520. | 2081 // No touch on desktop Mac. Tracked in http://crbug.com/445520. |
| (...skipping 1420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3501 // Moving the child to a different widget should call the removals observer. | 3502 // Moving the child to a different widget should call the removals observer. |
| 3502 WidgetAutoclosePtr widget2(CreateTopLevelPlatformWidget()); | 3503 WidgetAutoclosePtr widget2(CreateTopLevelPlatformWidget()); |
| 3503 widget2->client_view()->AddChildView(child); | 3504 widget2->client_view()->AddChildView(child); |
| 3504 EXPECT_TRUE(removals_observer.DidRemoveView(child)); | 3505 EXPECT_TRUE(removals_observer.DidRemoveView(child)); |
| 3505 | 3506 |
| 3506 widget->RemoveRemovalsObserver(&removals_observer); | 3507 widget->RemoveRemovalsObserver(&removals_observer); |
| 3507 } | 3508 } |
| 3508 | 3509 |
| 3509 } // namespace test | 3510 } // namespace test |
| 3510 } // namespace views | 3511 } // namespace views |
| OLD | NEW |