ClickDetectorTests.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/UnitTest/TestTypes.h>
  9. #include <AzFramework/Viewport/ClickDetector.h>
  10. #include <AzFramework/Viewport/ScreenGeometry.h>
  11. namespace AzFramework
  12. {
  13. std::ostream& operator<<(std::ostream& os, const ClickDetector::ClickOutcome clickOutcome)
  14. {
  15. switch (clickOutcome)
  16. {
  17. case ClickDetector::ClickOutcome::Click:
  18. os << "ClickOutcome::Click";
  19. break;
  20. case ClickDetector::ClickOutcome::Move:
  21. os << "ClickOutcome::Move";
  22. break;
  23. case ClickDetector::ClickOutcome::Release:
  24. os << "ClickOutcome::Release";
  25. break;
  26. case ClickDetector::ClickOutcome::Nil:
  27. os << "ClickOutcome::Nil";
  28. break;
  29. }
  30. return os;
  31. }
  32. } // namespace AzFramework
  33. namespace UnitTest
  34. {
  35. using AzFramework::ClickDetector;
  36. using AzFramework::ScreenVector;
  37. class ClickDetectorFixture : public ::testing::Test
  38. {
  39. public:
  40. ClickDetector m_clickDetector;
  41. };
  42. TEST_F(ClickDetectorFixture, ClickIsDetectedWithNoMouseMovementOnMouseUp)
  43. {
  44. using ::testing::Eq;
  45. const ClickDetector::ClickOutcome initialDownOutcome =
  46. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
  47. const ClickDetector::ClickOutcome initialUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
  48. EXPECT_THAT(initialDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
  49. EXPECT_THAT(initialUpOutcome, Eq(ClickDetector::ClickOutcome::Click));
  50. }
  51. TEST_F(ClickDetectorFixture, MoveIsDetectedWithMouseMovementAfterMouseDown)
  52. {
  53. using ::testing::Eq;
  54. const ClickDetector::ClickOutcome initialDownOutcome =
  55. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
  56. const ClickDetector::ClickOutcome initialMoveOutcome =
  57. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Nil, ScreenVector(10, 10));
  58. EXPECT_THAT(initialDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
  59. EXPECT_THAT(initialMoveOutcome, Eq(ClickDetector::ClickOutcome::Move));
  60. }
  61. TEST_F(ClickDetectorFixture, ReleaseIsDetectedAfterMouseMovementOnMouseUp)
  62. {
  63. using ::testing::Eq;
  64. const ClickDetector::ClickOutcome initialDownOutcome =
  65. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
  66. // move
  67. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Nil, ScreenVector(10, 10));
  68. const ClickDetector::ClickOutcome initialUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
  69. EXPECT_THAT(initialDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
  70. EXPECT_THAT(initialUpOutcome, Eq(ClickDetector::ClickOutcome::Release));
  71. }
  72. TEST_F(ClickDetectorFixture, MoveIsReturnedOnlyAfterFirstMouseMove)
  73. {
  74. using ::testing::Eq;
  75. const ClickDetector::ClickOutcome initialDownOutcome =
  76. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
  77. const ClickDetector::ClickOutcome initialMoveOutcome =
  78. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Nil, ScreenVector(10, 10));
  79. const ClickDetector::ClickOutcome secondaryMoveOutcome =
  80. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Nil, ScreenVector(10, 10));
  81. EXPECT_THAT(initialDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
  82. EXPECT_THAT(initialMoveOutcome, Eq(ClickDetector::ClickOutcome::Move));
  83. EXPECT_THAT(secondaryMoveOutcome, Eq(ClickDetector::ClickOutcome::Nil));
  84. }
  85. TEST_F(ClickDetectorFixture, ClickIsNotRegisteredAfterDoubleClick)
  86. {
  87. using ::testing::Eq;
  88. const ClickDetector::ClickOutcome initialDownOutcome =
  89. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
  90. const ClickDetector::ClickOutcome initialUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
  91. const ClickDetector::ClickOutcome secondaryDownOutcome =
  92. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
  93. const ClickDetector::ClickOutcome secondaryUpOutcome =
  94. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
  95. EXPECT_THAT(initialDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
  96. EXPECT_THAT(initialUpOutcome, Eq(ClickDetector::ClickOutcome::Click));
  97. EXPECT_THAT(secondaryDownOutcome, Eq(ClickDetector::ClickOutcome::Nil)); // double click
  98. EXPECT_THAT(secondaryUpOutcome, Eq(ClickDetector::ClickOutcome::Nil)); // click not registered
  99. }
  100. TEST_F(ClickDetectorFixture, ClickIsNotRegisteredAfterIgnoredDoubleClick)
  101. {
  102. using ::testing::Eq;
  103. const ClickDetector::ClickOutcome initialDownOutcome =
  104. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
  105. const ClickDetector::ClickOutcome initialUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
  106. const ClickDetector::ClickOutcome secondaryDownOutcome =
  107. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Nil, ScreenVector(0, 0));
  108. const ClickDetector::ClickOutcome secondaryUpOutcome =
  109. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
  110. EXPECT_THAT(initialDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
  111. EXPECT_THAT(initialUpOutcome, Eq(ClickDetector::ClickOutcome::Click));
  112. EXPECT_THAT(secondaryDownOutcome, Eq(ClickDetector::ClickOutcome::Nil)); // ignored double click
  113. EXPECT_THAT(secondaryUpOutcome, Eq(ClickDetector::ClickOutcome::Nil)); // click not registered
  114. }
  115. // if the click detector registers a mouse down event, but then all intermediate calls are ignored
  116. // (another system may start intercepting events and swallowing them) then when we do receive a mouse
  117. // up event we should ensure we take into account the current delta - if the delta is large, then the
  118. // outcome will be release
  119. TEST_F(ClickDetectorFixture, ClickIsNotRegisteredAfterIgnoringMouseMovesBeforeMouseUpWithLargeDelta)
  120. {
  121. using ::testing::Eq;
  122. const ClickDetector::ClickOutcome downOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
  123. const ClickDetector::ClickOutcome upOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(50, 50));
  124. EXPECT_THAT(downOutcome, Eq(ClickDetector::ClickOutcome::Nil));
  125. EXPECT_THAT(upOutcome, Eq(ClickDetector::ClickOutcome::Release));
  126. }
  127. //! note: ClickDetector does not explicitly return double clicks but if one occurs the ClickOutcome will be Nil
  128. TEST_F(ClickDetectorFixture, DoubleClickIsRegisteredIfMouseDeltaHasMovedLessThanDeadzoneInClickInterval)
  129. {
  130. using ::testing::Eq;
  131. const ClickDetector::ClickOutcome firstDownOutcome =
  132. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
  133. const ClickDetector::ClickOutcome firstUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
  134. const ClickDetector::ClickOutcome secondDownOutcome =
  135. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
  136. const ClickDetector::ClickOutcome secondUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
  137. EXPECT_THAT(firstDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
  138. EXPECT_THAT(firstUpOutcome, Eq(ClickDetector::ClickOutcome::Click));
  139. EXPECT_THAT(secondDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
  140. EXPECT_THAT(secondUpOutcome, Eq(ClickDetector::ClickOutcome::Nil));
  141. }
  142. TEST_F(ClickDetectorFixture, DoubleClickIsNotRegisteredIfMouseDeltaHasMovedMoreThanDeadzoneInClickInterval)
  143. {
  144. using ::testing::Eq;
  145. const ClickDetector::ClickOutcome firstDownOutcome =
  146. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
  147. const ClickDetector::ClickOutcome firstUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
  148. const ClickDetector::ClickOutcome secondDownOutcome =
  149. m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(10, 10));
  150. const ClickDetector::ClickOutcome secondUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
  151. EXPECT_THAT(firstDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
  152. EXPECT_THAT(firstUpOutcome, Eq(ClickDetector::ClickOutcome::Click));
  153. EXPECT_THAT(secondDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
  154. EXPECT_THAT(secondUpOutcome, Eq(ClickDetector::ClickOutcome::Click));
  155. }
  156. } // namespace UnitTest