inputTest.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // TODO: Include settings to adapt instructions for specific operating systems, such as control click and command click on MacOS and F keys for insert and pause.
  2. #include "inputTest.h"
  3. using namespace dsr;
  4. #define TASK_IS(INDEX) context.taskIndex == INDEX
  5. #define EVENT_TYPE_IS(TYPE) event.mouseEventType == MouseEventType::TYPE
  6. void inputTests_populate(List<Test> &target, int buttonCount, bool relative, bool verticalScroll) {
  7. if (buttonCount >= 3) {
  8. target.pushConstruct(
  9. U"Mouse button test"
  10. ,
  11. [](AlignedImageRgbaU8 &canvas, TestContext &context) {
  12. image_fill(canvas, ColorRgbaI32(255, 255, 255, 255));
  13. context.drawAides(canvas);
  14. if (TASK_IS(0)) {
  15. font_printLine(canvas, font_getDefault(), U"Press down the left mouse button.", IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  16. } else if (TASK_IS(1)) {
  17. font_printLine(canvas, font_getDefault(), U"Release the left mouse button.", IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  18. } else if (TASK_IS(2)) {
  19. font_printLine(canvas, font_getDefault(), U"Press down the right mouse button.", IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  20. } else if (TASK_IS(3)) {
  21. font_printLine(canvas, font_getDefault(), U"Release the right mouse button.", IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  22. } else if (TASK_IS(4)) {
  23. font_printLine(canvas, font_getDefault(), U"Press down the middle mouse button.", IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  24. } else if (TASK_IS(5)) {
  25. font_printLine(canvas, font_getDefault(), U"Release the middle mouse button.", IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  26. }
  27. // TODO: Draw expanding circles from lowering and raising buttons together with names of the keys used.
  28. // TODO: Draw fading lines from move events.
  29. }
  30. ,
  31. [](const MouseEvent& event, TestContext &context) {
  32. if (EVENT_TYPE_IS(MouseDown)) {
  33. if (TASK_IS(0) && event.key == MouseKeyEnum::Left) {
  34. context.passTask();
  35. } else if (TASK_IS(2) && event.key == MouseKeyEnum::Right) {
  36. context.passTask();
  37. } else if (TASK_IS(4) && event.key == MouseKeyEnum::Middle) {
  38. context.passTask();
  39. } else {
  40. sendWarning(U"Detected a different key!\n");
  41. }
  42. } else if (EVENT_TYPE_IS(MouseUp)) {
  43. if (TASK_IS(1) && event.key == MouseKeyEnum::Left) {
  44. context.passTask();
  45. } else if (TASK_IS(3) && event.key == MouseKeyEnum::Right) {
  46. context.passTask();
  47. } else if (TASK_IS(5) && event.key == MouseKeyEnum::Middle) {
  48. context.finishTest(Grade::Passed);
  49. } else {
  50. sendWarning(U"Detected a different key!\n");
  51. }
  52. }
  53. }
  54. ,
  55. [](const KeyboardEvent& event, TestContext &context) {
  56. sendWarning(U"Detected a keyboard event with ", event.dsrKey, " instead of a mouse button!\n");
  57. }
  58. ,
  59. false
  60. );
  61. } else {
  62. sendWarning(U"Skipped the mouse button test due to settings.\n");
  63. }
  64. if (buttonCount >= 1) {
  65. target.pushConstruct(
  66. U"Mouse drag test"
  67. ,
  68. [](AlignedImageRgbaU8 &canvas, TestContext &context) {
  69. image_fill(canvas, ColorRgbaI32(255, 255, 255, 255));
  70. context.drawAides(canvas);
  71. if (TASK_IS(0)) {
  72. font_printLine(canvas, font_getDefault(), U"Hover the cursor over the window.", IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  73. } else if (TASK_IS(1)) {
  74. font_printLine(canvas, font_getDefault(), U"Press down the left mouse key.", IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  75. } else if (TASK_IS(2)) {
  76. font_printLine(canvas, font_getDefault(), U"Drag the mouse over the window with the left key pressed down.", IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  77. } else if (TASK_IS(3)) {
  78. font_printLine(canvas, font_getDefault(), U"Release the left key.", IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  79. }
  80. }
  81. ,
  82. [](const MouseEvent& event, TestContext &context) {
  83. if (TASK_IS(0) && EVENT_TYPE_IS(MouseMove) && !context.leftMouseDown && !context.middleMouseDown && !context.rightMouseDown) {
  84. context.passTask();
  85. } else if (TASK_IS(1) && EVENT_TYPE_IS(MouseDown)) {
  86. if (event.key == MouseKeyEnum::Left) {
  87. context.passTask();
  88. } else {
  89. // TODO: Say which key was triggered instead and suggest skipping with escape if it can not be found.
  90. }
  91. } else if (TASK_IS(2) && EVENT_TYPE_IS(MouseMove) && context.leftMouseDown) {
  92. context.passTask();
  93. } else if (TASK_IS(3) && EVENT_TYPE_IS(MouseUp)) {
  94. if (event.key == MouseKeyEnum::Left) {
  95. context.finishTest(Grade::Passed);
  96. } else {
  97. // TODO: Say which key was triggered instead and suggest skipping with escape if it can not be found.
  98. }
  99. }
  100. }
  101. ,
  102. [](const KeyboardEvent& event, TestContext &context) {}
  103. ,
  104. false
  105. );
  106. } else {
  107. sendWarning(U"Skipped the mouse button drag test due to settings.\n");
  108. }
  109. if (buttonCount >= 1 && verticalScroll) {
  110. target.pushConstruct(
  111. U"Mouse scroll test"
  112. ,
  113. [](AlignedImageRgbaU8 &canvas, TestContext &context) {
  114. image_fill(canvas, ColorRgbaI32(255, 255, 255, 255));
  115. context.drawAides(canvas);
  116. // TODO: Show something moving in the background while scrolling to show the direction. Only pass once the end has been reached.
  117. if (TASK_IS(0)) {
  118. font_printLine(canvas, font_getDefault(), U"Scroll in the direction used to reach the top of a document by moving content down.", IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  119. } else if (TASK_IS(1)) {
  120. font_printLine(canvas, font_getDefault(), U"Click when you are done scrolling up.", IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  121. } else if (TASK_IS(2)) {
  122. font_printLine(canvas, font_getDefault(), U"Scroll in the direction used to reach the bottom of a document by moving content up.", IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  123. } else if (TASK_IS(3)) {
  124. font_printLine(canvas, font_getDefault(), U"Click when you are done scrolling down.", IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  125. }
  126. }
  127. ,
  128. [](const MouseEvent& event, TestContext &context) {
  129. // Due to many laptops having the scroll direction inverted by default so that draging down scrolls up
  130. // Comparing how scrolling works in external text editors would be a useful addition to this test,
  131. // because many users probably don't know what is scrolling up and what is scrolling down when the direction is inverted on a track-pad.
  132. if (TASK_IS(0) && EVENT_TYPE_IS(Scroll)) {
  133. if (event.key == MouseKeyEnum::ScrollUp) {
  134. context.passTask();
  135. } else if (event.key == MouseKeyEnum::ScrollDown) {
  136. // Just give a warning, because this test can be very
  137. sendWarning(U"Scroll down was detected when attempting to scroll up. Compare the scrolling direction of a textbox with an external text editor to ensure consistent behavior.\n");
  138. }
  139. } else if (TASK_IS(1) && EVENT_TYPE_IS(MouseDown)) {
  140. context.passTask();
  141. } else if (TASK_IS(2) && EVENT_TYPE_IS(Scroll)) {
  142. if (event.key == MouseKeyEnum::ScrollDown) {
  143. context.passTask();
  144. } else if (event.key == MouseKeyEnum::ScrollUp) {
  145. sendWarning(U"Scroll up was detected when attempting to scroll down. Compare the scrolling direction of a textbox with an external text editor to ensure consistent behavior.\n");
  146. }
  147. } else if (TASK_IS(3) && EVENT_TYPE_IS(MouseDown)) {
  148. context.finishTest(Grade::Passed);
  149. }
  150. }
  151. ,
  152. [](const KeyboardEvent& event, TestContext &context) {}
  153. ,
  154. false
  155. );
  156. } else {
  157. sendWarning(U"Skipped the vertical scroll test due to settings.\n");
  158. }
  159. target.pushConstruct(
  160. U"Keyboard test"
  161. ,
  162. [](AlignedImageRgbaU8 &canvas, TestContext &context) {
  163. image_fill(canvas, ColorRgbaI32(255, 255, 255, 255));
  164. // TODO: Draw a keyboard showing which key is expected and which key was detected.
  165. if (context.taskIndex < DsrKey::DsrKey_Unhandled) {
  166. font_printLine(canvas, font_getDefault(), string_combine(U"Press down ", (DsrKey)context.taskIndex, " on your physical or virtual keyboard."), IVector2D(40, 40), ColorRgbaI32(0, 0, 0, 255));
  167. }
  168. }
  169. ,
  170. [](const MouseEvent& event, TestContext &context) {
  171. sendWarning(U"Detected a mouse event with ", event.key, " instead of a keyboard event!\n");
  172. }
  173. ,
  174. [](const KeyboardEvent& event, TestContext &context) {
  175. if (event.keyboardEventType == KeyboardEventType::KeyDown && event.dsrKey == context.taskIndex) {
  176. // TODO: Require both down and up events.
  177. if (context.taskIndex >= DsrKey::DsrKey_Unhandled - 1) {
  178. context.finishTest(Grade::Passed);
  179. } else {
  180. context.passTask();
  181. // Skip testing the escape key, because it is currently reserved for skipping tests.
  182. if (context.taskIndex == DsrKey::DsrKey_Escape) {
  183. context.passTask();
  184. }
  185. }
  186. }
  187. }
  188. ,
  189. false
  190. );
  191. }