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