You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
6.2 KiB

  1. // Copyright 2023 Google LLC
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation, either version 2 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. #include "keyboard_report_util.hpp"
  16. #include "keycode.h"
  17. #include "test_common.hpp"
  18. #include "test_fixture.hpp"
  19. #include "test_keymap_key.hpp"
  20. using ::testing::_;
  21. using ::testing::AnyNumber;
  22. using ::testing::AnyOf;
  23. using ::testing::InSequence;
  24. using ::testing::TestParamInfo;
  25. namespace {
  26. struct ShiftKeyParams {
  27. std::string name;
  28. uint16_t keycode;
  29. uint16_t report_shift_code;
  30. static const std::string& GetName(const TestParamInfo<ShiftKeyParams>& info) {
  31. return info.param.name;
  32. }
  33. };
  34. class CapsWordInvertOnShift : public ::testing::WithParamInterface<ShiftKeyParams>, public TestFixture {
  35. void SetUp() override {
  36. caps_word_off();
  37. }
  38. };
  39. // With Caps Word on, type "A, 4, Shift(A, 4, A), A, Shift(A), 4".
  40. TEST_P(CapsWordInvertOnShift, ShiftWithinWord) {
  41. TestDriver driver;
  42. KeymapKey key_shift(0, 0, 0, GetParam().keycode);
  43. KeymapKey key_a(0, 1, 0, KC_A);
  44. KeymapKey key_4(0, 2, 0, KC_4);
  45. set_keymap({key_shift, key_a, key_4});
  46. // Allow any number of reports with no keys or only KC_LSFT.
  47. // clang-format off
  48. EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
  49. KeyboardReport(),
  50. KeyboardReport(KC_LSFT))))
  51. .Times(AnyNumber());
  52. // clang-format on
  53. { // Expect: "A4a$aAa4"
  54. InSequence s;
  55. EXPECT_REPORT(driver, (KC_LSFT, KC_A));
  56. EXPECT_REPORT(driver, (KC_4));
  57. EXPECT_REPORT(driver, (KC_A));
  58. EXPECT_REPORT(driver, (KC_LSFT, KC_4));
  59. EXPECT_REPORT(driver, (KC_A));
  60. EXPECT_REPORT(driver, (KC_LSFT, KC_A));
  61. EXPECT_REPORT(driver, (KC_A));
  62. EXPECT_REPORT(driver, (KC_4));
  63. }
  64. caps_word_on();
  65. tap_keys(key_a, key_4); // Type "A, 4".
  66. key_shift.press(); // Type "Shift(A, 4, A)".
  67. run_one_scan_loop();
  68. tap_keys(key_a, key_4, key_a);
  69. key_shift.release();
  70. run_one_scan_loop();
  71. tap_key(key_a); // Type "A".
  72. key_shift.press(); // Type "Shift(A)".
  73. run_one_scan_loop();
  74. tap_key(key_a);
  75. key_shift.release();
  76. run_one_scan_loop();
  77. tap_key(key_4); // Type "4".
  78. VERIFY_AND_CLEAR(driver);
  79. }
  80. TEST_P(CapsWordInvertOnShift, ShiftHeldAtWordEnd) {
  81. TestDriver driver;
  82. KeymapKey key_shift(0, 0, 0, GetParam().keycode);
  83. KeymapKey key_a(0, 1, 0, KC_A);
  84. KeymapKey key_slsh(0, 2, 0, KC_SLSH);
  85. set_keymap({key_shift, key_a, key_slsh});
  86. // Allow any number of reports with no keys or only KC_LSFT.
  87. // clang-format off
  88. EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
  89. KeyboardReport(),
  90. KeyboardReport(KC_LSFT),
  91. KeyboardReport(KC_RSFT))))
  92. .Times(AnyNumber());
  93. // clang-format on
  94. { // Expect: "Aa?A"
  95. InSequence s;
  96. EXPECT_REPORT(driver, (KC_LSFT, KC_A));
  97. EXPECT_REPORT(driver, (KC_A));
  98. EXPECT_REPORT(driver, (GetParam().report_shift_code, KC_SLSH));
  99. EXPECT_REPORT(driver, (GetParam().report_shift_code, KC_A));
  100. }
  101. caps_word_on();
  102. tap_key(key_a);
  103. key_shift.press(); // Press Shift.
  104. run_one_scan_loop();
  105. EXPECT_EQ(get_mods(), 0);
  106. tap_key(key_a);
  107. tap_key(key_slsh); // Tap '/' key, which is word breaking, ending Caps Word.
  108. EXPECT_FALSE(is_caps_word_on());
  109. EXPECT_EQ(get_mods(), MOD_BIT(GetParam().report_shift_code));
  110. tap_key(key_a);
  111. key_shift.release(); // Release Shift.
  112. run_one_scan_loop();
  113. EXPECT_EQ(get_mods(), 0);
  114. VERIFY_AND_CLEAR(driver);
  115. }
  116. TEST_P(CapsWordInvertOnShift, TwoShiftsHeld) {
  117. TestDriver driver;
  118. KeymapKey key_shift1(0, 0, 0, GetParam().keycode);
  119. KeymapKey key_shift2(0, 1, 0, GetParam().report_shift_code);
  120. KeymapKey key_a(0, 2, 0, KC_A);
  121. KeymapKey key_slsh(0, 3, 0, KC_SLSH);
  122. set_keymap({key_shift1, key_shift2, key_a, key_slsh});
  123. // Allow any number of reports with no keys or only KC_LSFT.
  124. // clang-format off
  125. EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
  126. KeyboardReport(),
  127. KeyboardReport(KC_LSFT),
  128. KeyboardReport(KC_RSFT))))
  129. .Times(AnyNumber());
  130. // clang-format on
  131. { // Expect: "Aa?a"
  132. InSequence s;
  133. EXPECT_REPORT(driver, (KC_LSFT, KC_A));
  134. EXPECT_REPORT(driver, (KC_A));
  135. EXPECT_REPORT(driver, (GetParam().report_shift_code, KC_SLSH));
  136. EXPECT_REPORT(driver, (KC_A));
  137. }
  138. caps_word_on();
  139. tap_key(key_a);
  140. key_shift1.press(); // Press shift1.
  141. run_one_scan_loop();
  142. EXPECT_EQ(get_mods(), 0);
  143. tap_key(key_a);
  144. tap_key(key_slsh); // Tap '/' key, which is word breaking, ending Caps Word.
  145. EXPECT_FALSE(is_caps_word_on());
  146. EXPECT_EQ(get_mods(), MOD_BIT(GetParam().report_shift_code));
  147. key_shift2.press(); // Press shift2.
  148. run_one_scan_loop();
  149. EXPECT_EQ(get_mods(), MOD_BIT(GetParam().report_shift_code));
  150. key_shift1.release(); // Release shift1.
  151. run_one_scan_loop();
  152. EXPECT_EQ(get_mods(), 0);
  153. tap_key(key_a);
  154. key_shift2.release(); // Release shift2.
  155. run_one_scan_loop();
  156. EXPECT_EQ(get_mods(), 0);
  157. VERIFY_AND_CLEAR(driver);
  158. }
  159. // clang-format off
  160. INSTANTIATE_TEST_CASE_P(
  161. Shifts,
  162. CapsWordInvertOnShift,
  163. ::testing::Values(
  164. ShiftKeyParams{"KC_LSFT", KC_LSFT, KC_LSFT},
  165. ShiftKeyParams{"KC_RSFT", KC_RSFT, KC_RSFT},
  166. ShiftKeyParams{"LSFT_T", LSFT_T(KC_A), KC_LSFT},
  167. ShiftKeyParams{"RSFT_T", RSFT_T(KC_A), KC_RSFT},
  168. ShiftKeyParams{"OSM_LSFT", OSM(MOD_LSFT), KC_LSFT},
  169. ShiftKeyParams{"OSM_RSFT", OSM(MOD_RSFT), KC_RSFT}
  170. ),
  171. ShiftKeyParams::GetName
  172. );
  173. // clang-format on
  174. } // namespace