view_android_unittest.cc 10 KB

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