jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 1 | // Copyright 2017 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. |
| 4 | |
jinsukkim | e9821146 | 2017-05-12 09:57:04 | [diff] [blame] | 5 | #include "base/test/gtest_util.h" |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 6 | #include "testing/gtest/include/gtest/gtest.h" |
| 7 | #include "ui/android/event_forwarder.h" |
| 8 | #include "ui/android/view_android.h" |
Jinsuk Kim | d5d29a2 | 2017-08-29 01:39:44 | [diff] [blame] | 9 | #include "ui/android/view_android_observer.h" |
Jinsuk Kim | d5d29a2 | 2017-08-29 01:39:44 | [diff] [blame] | 10 | #include "ui/android/window_android.h" |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 11 | #include "ui/events/android/event_handler_android.h" |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 12 | #include "ui/events/android/motion_event_android.h" |
Majid Valipour | 7f25668 | 2018-01-17 06:35:37 | [diff] [blame] | 13 | #include "ui/events/test/scoped_event_test_tick_clock.h" |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 14 | |
| 15 | namespace ui { |
| 16 | |
| 17 | using base::android::JavaParamRef; |
| 18 | |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 19 | class TestViewAndroid : public ViewAndroid { |
| 20 | public: |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 21 | TestViewAndroid(ViewAndroid::LayoutType layout_type) |
| 22 | : ViewAndroid(layout_type) {} |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 23 | |
| 24 | float GetDipScale() override { return 1.f; } |
| 25 | }; |
| 26 | |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 27 | class TestEventHandler : public EventHandlerAndroid { |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 28 | public: |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 29 | TestEventHandler() {} |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 30 | |
Jinsuk Kim | 2b85947 | 2017-08-30 02:47:19 | [diff] [blame] | 31 | bool OnTouchEvent(const MotionEventAndroid& event) override { |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 32 | touch_called_ = true; |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 33 | return handle_event_; |
| 34 | } |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 35 | void OnSizeChanged() override { onsize_called_ = true; } |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 36 | |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 37 | void SetHandleEvent(bool handle_event) { handle_event_ = handle_event; } |
| 38 | bool TouchEventHandled() { return touch_called_ && handle_event_; } |
| 39 | bool TouchEventCalled() { return touch_called_; } |
| 40 | bool OnSizeCalled() { return onsize_called_; } |
| 41 | void Reset() { |
| 42 | touch_called_ = false; |
| 43 | onsize_called_ = false; |
| 44 | } |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 45 | |
| 46 | private: |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 47 | bool handle_event_{true}; // Marks as event was consumed. True by default. |
| 48 | bool touch_called_{false}; |
| 49 | bool onsize_called_{false}; |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 50 | }; |
| 51 | |
| 52 | class ViewAndroidBoundsTest : public testing::Test { |
| 53 | public: |
| 54 | ViewAndroidBoundsTest() |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 55 | : root_(ViewAndroid::LayoutType::MATCH_PARENT), |
| 56 | view1_(ViewAndroid::LayoutType::NORMAL), |
| 57 | view2_(ViewAndroid::LayoutType::NORMAL), |
| 58 | view3_(ViewAndroid::LayoutType::NORMAL), |
| 59 | viewm_(ViewAndroid::LayoutType::MATCH_PARENT) { |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 60 | root_.GetEventForwarder(); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 61 | view1_.set_event_handler(&handler1_); |
| 62 | view2_.set_event_handler(&handler2_); |
| 63 | view3_.set_event_handler(&handler3_); |
| 64 | viewm_.set_event_handler(&handlerm_); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 65 | } |
| 66 | |
| 67 | void Reset() { |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 68 | handler1_.Reset(); |
| 69 | handler2_.Reset(); |
| 70 | handler3_.Reset(); |
| 71 | handlerm_.Reset(); |
Majid Valipour | 7f25668 | 2018-01-17 06:35:37 | [diff] [blame] | 72 | test_clock_.SetNowTicks(base::TimeTicks()); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 73 | } |
| 74 | |
| 75 | void GenerateTouchEventAt(float x, float y) { |
| 76 | ui::MotionEventAndroid::Pointer pointer0(0, x, y, 0, 0, 0, 0, 0); |
| 77 | ui::MotionEventAndroid::Pointer pointer1(0, 0, 0, 0, 0, 0, 0, 0); |
jinsukkim | b40b402c | 2017-03-29 09:39:08 | [diff] [blame] | 78 | ui::MotionEventAndroid event(nullptr, JavaParamRef<jobject>(nullptr), 1.f, |
Jinsuk Kim | 2b85947 | 2017-08-30 02:47:19 | [diff] [blame] | 79 | 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, false, |
jinsukkim | b40b402c | 2017-03-29 09:39:08 | [diff] [blame] | 80 | &pointer0, &pointer1); |
Jinsuk Kim | 2b85947 | 2017-08-30 02:47:19 | [diff] [blame] | 81 | root_.OnTouchEvent(event); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 82 | } |
| 83 | |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 84 | void ExpectHit(const TestEventHandler& hitHandler) { |
| 85 | TestEventHandler* handlers[4] = {&handler1_, &handler2_, &handler3_, |
| 86 | &handlerm_}; |
| 87 | for (auto* handler : handlers) { |
| 88 | if (&hitHandler == handler) |
| 89 | EXPECT_TRUE(handler->TouchEventHandled()); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 90 | else |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 91 | EXPECT_FALSE(handler->TouchEventHandled()); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 92 | } |
| 93 | Reset(); |
| 94 | } |
| 95 | |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 96 | TestViewAndroid root_; |
| 97 | TestViewAndroid view1_; |
| 98 | TestViewAndroid view2_; |
| 99 | TestViewAndroid view3_; |
Jinsuk Kim | 7d04c9e | 2017-09-13 00:22:18 | [diff] [blame] | 100 | TestViewAndroid viewm_; // match-parent view |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 101 | TestEventHandler handler1_; |
| 102 | TestEventHandler handler2_; |
| 103 | TestEventHandler handler3_; |
| 104 | TestEventHandler handlerm_; |
Majid Valipour | 7f25668 | 2018-01-17 06:35:37 | [diff] [blame] | 105 | ui::test::ScopedEventTestTickClock test_clock_; |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 106 | }; |
| 107 | |
| 108 | TEST_F(ViewAndroidBoundsTest, MatchesViewInFront) { |
Jinsuk Kim | 7d04c9e | 2017-09-13 00:22:18 | [diff] [blame] | 109 | view1_.SetLayoutForTesting(50, 50, 400, 600); |
| 110 | view2_.SetLayoutForTesting(50, 50, 400, 600); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 111 | root_.AddChild(&view2_); |
| 112 | root_.AddChild(&view1_); |
| 113 | |
| 114 | GenerateTouchEventAt(100.f, 100.f); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 115 | ExpectHit(handler1_); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 116 | |
| 117 | // View 2 moves up to the top, and events should hit it from now. |
| 118 | root_.MoveToFront(&view2_); |
| 119 | GenerateTouchEventAt(100.f, 100.f); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 120 | ExpectHit(handler2_); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 121 | } |
| 122 | |
| 123 | TEST_F(ViewAndroidBoundsTest, MatchesViewArea) { |
Jinsuk Kim | 7d04c9e | 2017-09-13 00:22:18 | [diff] [blame] | 124 | view1_.SetLayoutForTesting(50, 50, 200, 200); |
| 125 | view2_.SetLayoutForTesting(20, 20, 400, 600); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 126 | |
| 127 | root_.AddChild(&view2_); |
| 128 | root_.AddChild(&view1_); |
| 129 | |
| 130 | // Falls within |view1_|'s bounds |
| 131 | GenerateTouchEventAt(100.f, 100.f); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 132 | ExpectHit(handler1_); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 133 | |
| 134 | // Falls within |view2_|'s bounds |
| 135 | GenerateTouchEventAt(300.f, 400.f); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 136 | ExpectHit(handler2_); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 137 | } |
| 138 | |
| 139 | TEST_F(ViewAndroidBoundsTest, MatchesViewAfterMove) { |
Jinsuk Kim | 7d04c9e | 2017-09-13 00:22:18 | [diff] [blame] | 140 | view1_.SetLayoutForTesting(50, 50, 200, 200); |
| 141 | view2_.SetLayoutForTesting(20, 20, 400, 600); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 142 | root_.AddChild(&view2_); |
| 143 | root_.AddChild(&view1_); |
| 144 | |
| 145 | GenerateTouchEventAt(100.f, 100.f); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 146 | ExpectHit(handler1_); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 147 | |
Jinsuk Kim | 7d04c9e | 2017-09-13 00:22:18 | [diff] [blame] | 148 | view1_.SetLayoutForTesting(150, 150, 200, 200); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 149 | GenerateTouchEventAt(100.f, 100.f); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 150 | ExpectHit(handler2_); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 151 | } |
| 152 | |
| 153 | TEST_F(ViewAndroidBoundsTest, MatchesViewSizeOfkMatchParent) { |
Jinsuk Kim | 7d04c9e | 2017-09-13 00:22:18 | [diff] [blame] | 154 | view1_.SetLayoutForTesting(20, 20, 400, 600); |
| 155 | view2_.SetLayoutForTesting(50, 50, 200, 200); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 156 | |
| 157 | root_.AddChild(&view1_); |
| 158 | root_.AddChild(&view2_); |
Jinsuk Kim | 7d04c9e | 2017-09-13 00:22:18 | [diff] [blame] | 159 | view1_.AddChild(&viewm_); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 160 | |
| 161 | GenerateTouchEventAt(100.f, 100.f); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 162 | ExpectHit(handler2_); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 163 | |
| 164 | GenerateTouchEventAt(300.f, 400.f); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 165 | ExpectHit(handler1_); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 166 | |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 167 | handler1_.SetHandleEvent(false); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 168 | GenerateTouchEventAt(300.f, 400.f); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 169 | EXPECT_TRUE(handler1_.TouchEventCalled()); |
| 170 | ExpectHit(handlerm_); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 171 | } |
| 172 | |
| 173 | TEST_F(ViewAndroidBoundsTest, MatchesViewsWithOffset) { |
Jinsuk Kim | 7d04c9e | 2017-09-13 00:22:18 | [diff] [blame] | 174 | view1_.SetLayoutForTesting(10, 20, 150, 100); |
| 175 | view2_.SetLayoutForTesting(20, 30, 40, 30); |
| 176 | view3_.SetLayoutForTesting(70, 30, 40, 30); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 177 | |
| 178 | root_.AddChild(&view1_); |
| 179 | view1_.AddChild(&view2_); |
| 180 | view1_.AddChild(&view3_); |
| 181 | |
| 182 | GenerateTouchEventAt(70, 30); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 183 | ExpectHit(handler1_); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 184 | |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 185 | handler1_.SetHandleEvent(false); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 186 | GenerateTouchEventAt(40, 60); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 187 | EXPECT_TRUE(handler1_.TouchEventCalled()); |
| 188 | ExpectHit(handler2_); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 189 | |
| 190 | GenerateTouchEventAt(100, 70); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 191 | EXPECT_TRUE(handler1_.TouchEventCalled()); |
| 192 | ExpectHit(handler3_); |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 193 | } |
| 194 | |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 195 | TEST_F(ViewAndroidBoundsTest, OnSizeChanged) { |
| 196 | root_.AddChild(&view1_); |
Jinsuk Kim | 7d04c9e | 2017-09-13 00:22:18 | [diff] [blame] | 197 | view1_.AddChild(&viewm_); |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 198 | view1_.AddChild(&view3_); |
| 199 | |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 200 | // Size event propagates to non-match-parent children only. |
| 201 | view1_.OnSizeChanged(100, 100); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 202 | EXPECT_TRUE(handler1_.OnSizeCalled()); |
| 203 | EXPECT_TRUE(handlerm_.OnSizeCalled()); |
| 204 | EXPECT_FALSE(handler3_.OnSizeCalled()); |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 205 | |
| 206 | Reset(); |
| 207 | |
Jinsuk Kim | 7d04c9e | 2017-09-13 00:22:18 | [diff] [blame] | 208 | // Match-parent view should not receivee size events in the first place. |
| 209 | EXPECT_DCHECK_DEATH(viewm_.OnSizeChanged(100, 200)); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 210 | EXPECT_FALSE(handlerm_.OnSizeCalled()); |
| 211 | EXPECT_FALSE(handler3_.OnSizeCalled()); |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 212 | |
Jinsuk Kim | d602a12a | 2017-12-14 01:27:19 | [diff] [blame] | 213 | viewm_.RemoveFromParent(); |
| 214 | viewm_.OnSizeChangedInternal(gfx::Size(0, 0)); // Reset the size. |
| 215 | |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 216 | Reset(); |
| 217 | |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 218 | view1_.OnSizeChanged(100, 100); |
| 219 | |
| 220 | // Size event is generated for a newly added, match-parent child view. |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 221 | EXPECT_FALSE(handlerm_.OnSizeCalled()); |
Jinsuk Kim | 7d04c9e | 2017-09-13 00:22:18 | [diff] [blame] | 222 | view1_.AddChild(&viewm_); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 223 | EXPECT_TRUE(handlerm_.OnSizeCalled()); |
| 224 | EXPECT_FALSE(handler3_.OnSizeCalled()); |
Jinsuk Kim | d602a12a | 2017-12-14 01:27:19 | [diff] [blame] | 225 | |
| 226 | viewm_.RemoveFromParent(); |
| 227 | |
| 228 | Reset(); |
| 229 | |
| 230 | view1_.OnSizeChanged(100, 100); |
| 231 | |
| 232 | // Size event won't propagate if the children already have the same size. |
| 233 | view1_.AddChild(&viewm_); |
Jinsuk Kim | 1f8f47a3 | 2018-04-23 02:08:22 | [diff] [blame^] | 234 | EXPECT_FALSE(handlerm_.OnSizeCalled()); |
| 235 | EXPECT_FALSE(handler3_.OnSizeCalled()); |
Jinsuk Kim | 86071c8 | 2017-09-07 00:49:05 | [diff] [blame] | 236 | } |
| 237 | |
jinsukkim | e9821146 | 2017-05-12 09:57:04 | [diff] [blame] | 238 | TEST(ViewAndroidTest, ChecksMultipleEventForwarders) { |
| 239 | ViewAndroid parent; |
| 240 | ViewAndroid child; |
| 241 | parent.GetEventForwarder(); |
| 242 | child.GetEventForwarder(); |
| 243 | EXPECT_DCHECK_DEATH(parent.AddChild(&child)); |
| 244 | |
| 245 | ViewAndroid parent2; |
| 246 | ViewAndroid child2; |
| 247 | parent2.GetEventForwarder(); |
| 248 | parent2.AddChild(&child2); |
| 249 | EXPECT_DCHECK_DEATH(child2.GetEventForwarder()); |
| 250 | |
| 251 | ViewAndroid window; |
| 252 | ViewAndroid wcv1, wcv2; |
| 253 | ViewAndroid rwhv1a, rwhv1b, rwhv2; |
| 254 | wcv1.GetEventForwarder(); |
| 255 | wcv2.GetEventForwarder(); |
| 256 | |
| 257 | window.AddChild(&wcv1); |
| 258 | wcv1.AddChild(&rwhv1a); |
| 259 | wcv1.AddChild(&rwhv1b); |
| 260 | |
| 261 | wcv2.AddChild(&rwhv2); |
| 262 | |
| 263 | // window should be able to add wcv2 since there's only one event forwarder |
| 264 | // in the path window - wcv2* - rwvh2 |
| 265 | window.AddChild(&wcv2); |
| 266 | |
| 267 | // Additional event forwarder will cause failure. |
| 268 | EXPECT_DCHECK_DEATH(rwhv2.GetEventForwarder()); |
| 269 | } |
| 270 | |
Jinsuk Kim | d5d29a2 | 2017-08-29 01:39:44 | [diff] [blame] | 271 | class Observer : public ViewAndroidObserver { |
| 272 | public: |
| 273 | Observer() : attached_(false) {} |
| 274 | |
| 275 | void OnAttachedToWindow() override { attached_ = true; } |
| 276 | |
| 277 | void OnDetachedFromWindow() override { attached_ = false; } |
| 278 | |
| 279 | bool attached_; |
| 280 | }; |
| 281 | |
| 282 | TEST(ViewAndroidTest, Observer) { |
| 283 | std::unique_ptr<WindowAndroid> window(WindowAndroid::CreateForTesting()); |
| 284 | ViewAndroid top; |
| 285 | ViewAndroid bottom; |
| 286 | |
| 287 | Observer top_observer; |
| 288 | Observer bottom_observer; |
| 289 | |
| 290 | top.AddObserver(&top_observer); |
| 291 | bottom.AddObserver(&bottom_observer); |
| 292 | |
| 293 | top.AddChild(&bottom); |
| 294 | |
| 295 | EXPECT_FALSE(top_observer.attached_); |
| 296 | EXPECT_FALSE(bottom_observer.attached_); |
| 297 | |
| 298 | // Views in a tree all get notified of 'attached' event. |
| 299 | window->AddChild(&top); |
| 300 | EXPECT_TRUE(top_observer.attached_); |
| 301 | EXPECT_TRUE(bottom_observer.attached_); |
| 302 | |
| 303 | // Observer, upon addition, does not get notified of the current |
| 304 | // attached state. |
| 305 | Observer top_observer2; |
| 306 | top.AddObserver(&top_observer2); |
| 307 | EXPECT_FALSE(top_observer2.attached_); |
| 308 | |
| 309 | bottom.RemoveFromParent(); |
| 310 | EXPECT_FALSE(bottom_observer.attached_); |
| 311 | top.RemoveFromParent(); |
| 312 | EXPECT_FALSE(top_observer.attached_); |
| 313 | |
| 314 | window->AddChild(&top); |
| 315 | EXPECT_TRUE(top_observer.attached_); |
| 316 | |
| 317 | // View, upon addition to a tree in the attached state, should be notified. |
| 318 | top.AddChild(&bottom); |
| 319 | EXPECT_TRUE(bottom_observer.attached_); |
| 320 | |
| 321 | // Views in a tree all get notified of 'detached' event. |
| 322 | top.RemoveFromParent(); |
| 323 | EXPECT_FALSE(top_observer.attached_); |
| 324 | EXPECT_FALSE(bottom_observer.attached_); |
| 325 | } |
| 326 | |
jinsukkim | 5c3a120 | 2017-03-10 00:02:14 | [diff] [blame] | 327 | } // namespace ui |