keyboard stuff
1/* Copyright 2017 Fred Sundvik
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 */
16
17#include "keycode.h"
18#include "test_common.hpp"
19
20using testing::_;
21using testing::InSequence;
22
23class KeyPress : public TestFixture {};
24
25TEST_F(KeyPress, SendKeyboardIsNotCalledWhenNoKeyIsPressed) {
26 TestDriver driver;
27 EXPECT_NO_REPORT(driver);
28 keyboard_task();
29}
30
31TEST_F(KeyPress, CorrectKeyIsReportedWhenPressed) {
32 TestDriver driver;
33 auto key = KeymapKey(0, 0, 0, KC_A);
34
35 set_keymap({key});
36
37 key.press();
38 EXPECT_REPORT(driver, (key.report_code));
39 keyboard_task();
40
41 key.release();
42 EXPECT_EMPTY_REPORT(driver);
43 keyboard_task();
44}
45
46TEST_F(KeyPress, ANonMappedKeyDoesNothing) {
47 TestDriver driver;
48 auto key = KeymapKey(0, 0, 0, KC_NO);
49
50 set_keymap({key});
51
52 key.press();
53 EXPECT_NO_REPORT(driver);
54 keyboard_task();
55 keyboard_task();
56}
57
58TEST_F(KeyPress, CorrectKeysAreReportedWhenTwoKeysArePressed) {
59 TestDriver driver;
60 auto key_b = KeymapKey(0, 0, 0, KC_B);
61 auto key_c = KeymapKey(0, 1, 1, KC_C);
62
63 set_keymap({key_b, key_c});
64
65 key_b.press();
66 key_c.press();
67 EXPECT_REPORT(driver, (key_b.report_code));
68 EXPECT_REPORT(driver, (key_b.report_code, key_c.report_code));
69 keyboard_task();
70
71 key_b.release();
72 key_c.release();
73 // Note that the first key released is the first one in the matrix order
74 EXPECT_REPORT(driver, (key_c.report_code));
75 EXPECT_EMPTY_REPORT(driver);
76 keyboard_task();
77}
78
79TEST_F(KeyPress, LeftShiftIsReportedCorrectly) {
80 TestDriver driver;
81 auto key_a = KeymapKey(0, 0, 0, KC_A);
82 auto key_lsft = KeymapKey(0, 3, 0, KC_LEFT_SHIFT);
83
84 set_keymap({key_a, key_lsft});
85
86 key_lsft.press();
87 key_a.press();
88
89 EXPECT_REPORT(driver, (key_a.report_code));
90 EXPECT_REPORT(driver, (key_a.report_code, key_lsft.report_code));
91 keyboard_task();
92
93 key_a.release();
94 EXPECT_REPORT(driver, (key_lsft.report_code));
95 keyboard_task();
96
97 key_lsft.release();
98 EXPECT_EMPTY_REPORT(driver);
99 keyboard_task();
100}
101
102TEST_F(KeyPress, PressLeftShiftAndControl) {
103 TestDriver driver;
104 auto key_lsft = KeymapKey(0, 3, 0, KC_LEFT_SHIFT);
105 auto key_lctrl = KeymapKey(0, 5, 0, KC_LEFT_CTRL);
106
107 set_keymap({key_lctrl, key_lsft});
108
109 key_lsft.press();
110 key_lctrl.press();
111
112 EXPECT_REPORT(driver, (key_lsft.report_code));
113 EXPECT_REPORT(driver, (key_lsft.report_code, key_lctrl.report_code));
114 keyboard_task();
115
116 key_lsft.release();
117 key_lctrl.release();
118
119 EXPECT_REPORT(driver, (key_lctrl.report_code));
120 EXPECT_EMPTY_REPORT(driver);
121 keyboard_task();
122}
123
124TEST_F(KeyPress, LeftAndRightShiftCanBePressedAtTheSameTime) {
125 TestDriver driver;
126 auto key_lsft = KeymapKey(0, 3, 0, KC_LEFT_SHIFT);
127 auto key_rsft = KeymapKey(0, 4, 0, KC_RIGHT_SHIFT);
128
129 set_keymap({key_rsft, key_lsft});
130
131 key_lsft.press();
132 key_rsft.press();
133 EXPECT_REPORT(driver, (key_lsft.report_code));
134 EXPECT_REPORT(driver, (key_lsft.report_code, key_rsft.report_code));
135 keyboard_task();
136
137 key_lsft.release();
138 key_rsft.release();
139 EXPECT_REPORT(driver, (key_rsft.report_code));
140 EXPECT_EMPTY_REPORT(driver);
141 keyboard_task();
142}
143
144TEST_F(KeyPress, RightShiftLeftControlAndCharWithTheSameKey) {
145 TestDriver driver;
146 auto combo_key = KeymapKey(0, 0, 0, RSFT(LCTL(KC_O)));
147
148 set_keymap({combo_key});
149
150 // BUG: The press is split into two reports
151 // BUG: It reports RSFT instead of LSFT
152 // See issue #524 for more information
153 // The underlying cause is that we use only one bit to represent the right hand
154 // modifiers.
155 combo_key.press();
156 EXPECT_REPORT(driver, (KC_RIGHT_SHIFT, KC_RIGHT_CTRL));
157 EXPECT_REPORT(driver, (KC_RIGHT_SHIFT, KC_RIGHT_CTRL, KC_O));
158 keyboard_task();
159
160 combo_key.release();
161 EXPECT_REPORT(driver, (KC_RIGHT_SHIFT, KC_RIGHT_CTRL));
162 EXPECT_EMPTY_REPORT(driver);
163 keyboard_task();
164}
165
166TEST_F(KeyPress, PressPlusEqualReleaseBeforePress) {
167 TestDriver driver;
168 InSequence s;
169 auto key_plus = KeymapKey(0, 1, 1, KC_PLUS);
170 auto key_eql = KeymapKey(0, 0, 1, KC_EQUAL);
171
172 set_keymap({key_plus, key_eql});
173
174 key_plus.press();
175 EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
176 EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_EQUAL));
177 run_one_scan_loop();
178 VERIFY_AND_CLEAR(driver);
179
180 key_plus.release();
181 EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
182 EXPECT_EMPTY_REPORT(driver);
183 run_one_scan_loop();
184 VERIFY_AND_CLEAR(driver);
185
186 key_eql.press();
187 EXPECT_REPORT(driver, (key_eql.report_code));
188 run_one_scan_loop();
189 VERIFY_AND_CLEAR(driver);
190
191 key_eql.release();
192 EXPECT_EMPTY_REPORT(driver);
193 run_one_scan_loop();
194 VERIFY_AND_CLEAR(driver);
195}
196
197TEST_F(KeyPress, PressPlusEqualDontReleaseBeforePress) {
198 TestDriver driver;
199 InSequence s;
200 auto key_plus = KeymapKey(0, 1, 1, KC_PLUS);
201 auto key_eql = KeymapKey(0, 0, 1, KC_EQUAL);
202
203 set_keymap({key_plus, key_eql});
204
205 key_plus.press();
206 EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
207 EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_EQUAL));
208 run_one_scan_loop();
209 VERIFY_AND_CLEAR(driver);
210
211 key_eql.press();
212 EXPECT_EMPTY_REPORT(driver);
213 EXPECT_REPORT(driver, (KC_EQUAL));
214 run_one_scan_loop();
215 VERIFY_AND_CLEAR(driver);
216
217 key_plus.release();
218 // BUG: Should really still return KC_EQUAL, but this is fine too
219 EXPECT_EMPTY_REPORT(driver);
220 run_one_scan_loop();
221 VERIFY_AND_CLEAR(driver);
222
223 key_eql.release();
224 EXPECT_NO_REPORT(driver);
225 run_one_scan_loop();
226 VERIFY_AND_CLEAR(driver);
227}
228
229TEST_F(KeyPress, PressEqualPlusReleaseBeforePress) {
230 TestDriver driver;
231 InSequence s;
232 auto key_plus = KeymapKey(0, 1, 1, KC_PLUS);
233 auto key_eql = KeymapKey(0, 0, 1, KC_EQUAL);
234
235 set_keymap({key_plus, key_eql});
236
237 key_eql.press();
238 EXPECT_REPORT(driver, (KC_EQUAL));
239 run_one_scan_loop();
240 VERIFY_AND_CLEAR(driver);
241
242 key_eql.release();
243 EXPECT_EMPTY_REPORT(driver);
244 run_one_scan_loop();
245 VERIFY_AND_CLEAR(driver);
246
247 key_plus.press();
248 EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
249 EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_EQUAL));
250 run_one_scan_loop();
251 VERIFY_AND_CLEAR(driver);
252
253 key_plus.release();
254 EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
255 EXPECT_EMPTY_REPORT(driver);
256 run_one_scan_loop();
257 VERIFY_AND_CLEAR(driver);
258}
259
260TEST_F(KeyPress, PressEqualPlusDontReleaseBeforePress) {
261 TestDriver driver;
262 InSequence s;
263 auto key_plus = KeymapKey(0, 1, 1, KC_PLUS);
264 auto key_eql = KeymapKey(0, 0, 1, KC_EQUAL);
265
266 set_keymap({key_plus, key_eql});
267
268 key_eql.press();
269 EXPECT_REPORT(driver, (KC_EQUAL));
270 run_one_scan_loop();
271 VERIFY_AND_CLEAR(driver);
272
273 key_plus.press();
274 // BUG: The sequence is a bit strange, but it works, the end result is that
275 // KC_PLUS is sent
276 EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_EQUAL));
277 EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
278 EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_EQUAL));
279 run_one_scan_loop();
280 VERIFY_AND_CLEAR(driver);
281
282 key_eql.release();
283 // I guess it's fine to still report shift here
284 EXPECT_REPORT(driver, (KC_LEFT_SHIFT));
285 run_one_scan_loop();
286 VERIFY_AND_CLEAR(driver);
287
288 key_plus.release();
289 EXPECT_EMPTY_REPORT(driver);
290 run_one_scan_loop();
291 VERIFY_AND_CLEAR(driver);
292}