1 /*
2  *  Copyright (c) 2012 Dmitry Kazakov <dimula73@gmail.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include "kis_input_manager_test.h"
20 
21 #include <QTest>
22 
23 #include <QMouseEvent>
24 
25 #include "input/kis_single_action_shortcut.h"
26 #include "input/kis_stroke_shortcut.h"
27 #include "input/kis_abstract_input_action.h"
28 #include "input/kis_shortcut_matcher.h"
29 
30 
testSingleActionShortcut()31 void KisInputManagerTest::testSingleActionShortcut()
32 {
33     KisSingleActionShortcut s(0,0);
34     s.setKey(QSet<Qt::Key>() << Qt::Key_Shift, Qt::Key_Space);
35 
36     QVERIFY(s.match(QSet<Qt::Key>() << Qt::Key_Shift, Qt::Key_Space));
37     QVERIFY(!s.match(QSet<Qt::Key>() << Qt::Key_Control, Qt::Key_Space));
38     QVERIFY(!s.match(QSet<Qt::Key>(), Qt::Key_Space));
39     QVERIFY(!s.match(QSet<Qt::Key>() << Qt::Key_Shift, Qt::Key_Escape));
40     QVERIFY(!s.match(QSet<Qt::Key>() << Qt::Key_Shift, KisSingleActionShortcut::WheelUp));
41 
42     s.setWheel(QSet<Qt::Key>() << Qt::Key_Shift, KisSingleActionShortcut::WheelUp);
43 
44     QVERIFY(!s.match(QSet<Qt::Key>() << Qt::Key_Shift, Qt::Key_Space));
45     QVERIFY(!s.match(QSet<Qt::Key>() << Qt::Key_Control, Qt::Key_Space));
46     QVERIFY(!s.match(QSet<Qt::Key>(), Qt::Key_Space));
47     QVERIFY(!s.match(QSet<Qt::Key>() << Qt::Key_Shift, Qt::Key_Escape));
48     QVERIFY(s.match(QSet<Qt::Key>() << Qt::Key_Shift, KisSingleActionShortcut::WheelUp));
49 }
50 
testStrokeShortcut()51 void KisInputManagerTest::testStrokeShortcut()
52 {
53     KisStrokeShortcut s(0,0);
54     s.setButtons(QSet<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
55                  QSet<Qt::MouseButton>() << Qt::LeftButton);
56 
57     QVERIFY(s.matchReady(QSet<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
58                          QSet<Qt::MouseButton>() << Qt::LeftButton));
59 
60     QVERIFY(s.matchReady(QSet<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
61                          QSet<Qt::MouseButton>()));
62 
63     QVERIFY(!s.matchReady(QSet<Qt::Key>() << Qt::Key_Control << Qt::Key_Alt,
64                          QSet<Qt::MouseButton>()));
65 
66     QVERIFY(!s.matchReady(QSet<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
67                          QSet<Qt::MouseButton>() << Qt::RightButton));
68 
69     QVERIFY(s.matchBegin(Qt::LeftButton));
70     QVERIFY(!s.matchBegin(Qt::RightButton));
71 }
72 
73 struct TestingAction : public KisAbstractInputAction
74 {
TestingActionTestingAction75     TestingAction() : KisAbstractInputAction("TestingAction"), m_isHighResolution(false) { reset(); }
~TestingActionTestingAction76     ~TestingAction() {}
77 
beginTestingAction78     void begin(int shortcut, QEvent *event) { m_beginIndex = shortcut; m_beginNonNull = event;}
endTestingAction79     void end(QEvent *event) { m_ended = true; m_endNonNull = event; }
inputEventTestingAction80     void inputEvent(QEvent* event) { Q_UNUSED(event); m_gotInput = true; }
81 
resetTestingAction82     void reset() {
83         m_beginIndex = -1;
84         m_ended = false;
85         m_gotInput = false;
86         m_beginNonNull = false;
87         m_endNonNull = false;
88     }
89 
supportsHiResInputEventsTestingAction90     bool supportsHiResInputEvents() const {
91         return m_isHighResolution;
92     }
93 
setHighResInputEventsTestingAction94     void setHighResInputEvents(bool value) {
95         m_isHighResolution = value;
96     }
97 
98     int m_beginIndex;
99     bool m_ended;
100     bool m_gotInput;
101     bool m_beginNonNull;
102     bool m_endNonNull;
103 
104     bool m_isHighResolution;
105 };
106 
createKeyShortcut(KisAbstractInputAction * action,int shortcutIndex,const QSet<Qt::Key> & modifiers,Qt::Key key)107 KisSingleActionShortcut* createKeyShortcut(KisAbstractInputAction *action,
108                                   int shortcutIndex,
109                                   const QSet<Qt::Key> &modifiers,
110                                   Qt::Key key)
111 {
112     KisSingleActionShortcut *s = new KisSingleActionShortcut(action, shortcutIndex);
113     s->setKey(modifiers, key);
114     return s;
115 }
116 
createStrokeShortcut(KisAbstractInputAction * action,int shortcutIndex,const QSet<Qt::Key> & modifiers,Qt::MouseButton button)117 KisStrokeShortcut* createStrokeShortcut(KisAbstractInputAction *action,
118                                      int shortcutIndex,
119                                      const QSet<Qt::Key> &modifiers,
120                                      Qt::MouseButton button)
121 {
122     KisStrokeShortcut *s = new KisStrokeShortcut(action, shortcutIndex);
123     s->setButtons(modifiers, QSet<Qt::MouseButton>() << button);
124     return s;
125 }
126 
testKeyEvents()127 void KisInputManagerTest::testKeyEvents()
128 {
129     KisShortcutMatcher m;
130     m.enterEvent();
131 
132     TestingAction *a = new TestingAction();
133 
134 
135     m.addShortcut(
136         createKeyShortcut(a, 10,
137                           QSet<Qt::Key>() << Qt::Key_Shift,
138                           Qt::Key_Enter));
139 
140     m.addShortcut(
141         createKeyShortcut(a, 11,
142                           QSet<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
143                           Qt::Key_Enter));
144 
145     m.addShortcut(
146         createStrokeShortcut(a, 12,
147                              QSet<Qt::Key>() << Qt::Key_Shift,
148                              Qt::RightButton));
149 
150     m.addShortcut(
151         createStrokeShortcut(a, 13,
152                              QSet<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
153                              Qt::LeftButton));
154 
155     QCOMPARE(a->m_beginIndex, -1);
156 
157     // Test event with random values
158     QMouseEvent mouseEvent(QEvent::MouseMove, QPoint(),
159                            Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
160 
161     // Press Ctrl+Shift
162     QVERIFY(!m.keyPressed(Qt::Key_Shift));
163     QCOMPARE(a->m_beginIndex, -1);
164 
165     QVERIFY(!m.keyPressed(Qt::Key_Control));
166     QCOMPARE(a->m_beginIndex, -1);
167 
168 
169     // Complete Ctrl+Shift+Enter shortcut
170     QVERIFY(m.keyPressed(Qt::Key_Enter));
171     QCOMPARE(a->m_beginIndex, 11);
172     QCOMPARE(a->m_ended, true);
173     QCOMPARE(a->m_beginNonNull, false);
174     QCOMPARE(a->m_endNonNull, false);
175     a->reset();
176 
177 
178     // Pressing mouse buttons is disabled since Enter is pressed
179     QVERIFY(!m.buttonPressed(Qt::LeftButton, &mouseEvent));
180     QCOMPARE(a->m_beginIndex, -1);
181     QVERIFY(!m.buttonReleased(Qt::LeftButton, &mouseEvent));
182     QCOMPARE(a->m_beginIndex, -1);
183 
184 
185     // Release Enter, so the system should be ready for new shortcuts
186     QVERIFY(!m.keyReleased(Qt::Key_Enter));
187     QCOMPARE(a->m_beginIndex, -1);
188 
189 
190     // Complete Ctrl+Shift+LB shortcut
191     QVERIFY(m.buttonPressed(Qt::LeftButton, &mouseEvent));
192     QCOMPARE(a->m_beginIndex, 13);
193     QCOMPARE(a->m_ended, false);
194     QCOMPARE(a->m_beginNonNull, true);
195     QCOMPARE(a->m_endNonNull, false);
196     a->reset();
197 
198     QVERIFY(m.buttonReleased(Qt::LeftButton, &mouseEvent));
199     QCOMPARE(a->m_beginIndex, -1);
200     QCOMPARE(a->m_ended, true);
201     QCOMPARE(a->m_beginNonNull, false);
202     QCOMPARE(a->m_endNonNull, true);
203     a->reset();
204 
205 
206     // There is no Ctrl+Shift+RB shortcut
207     QVERIFY(!m.buttonPressed(Qt::RightButton, &mouseEvent));
208     QCOMPARE(a->m_beginIndex, -1);
209 
210     QVERIFY(!m.buttonReleased(Qt::RightButton, &mouseEvent));
211     QCOMPARE(a->m_beginIndex, -1);
212 
213 
214     // Check that Ctrl+Shift+Enter is still enabled
215     QVERIFY(m.keyPressed(Qt::Key_Enter));
216     QCOMPARE(a->m_beginIndex, 11);
217     QCOMPARE(a->m_ended, true);
218     QCOMPARE(a->m_beginNonNull, false);
219     QCOMPARE(a->m_endNonNull, false);
220     a->reset();
221 
222     // Check autorepeat
223     QVERIFY(m.autoRepeatedKeyPressed(Qt::Key_Enter));
224     QCOMPARE(a->m_beginIndex, 11);
225     QCOMPARE(a->m_ended, true);
226     QCOMPARE(a->m_beginNonNull, false);
227     QCOMPARE(a->m_endNonNull, false);
228     a->reset();
229 
230     QVERIFY(!m.keyReleased(Qt::Key_Enter));
231     QCOMPARE(a->m_beginIndex, -1);
232 
233 
234     // Release Ctrl
235     QVERIFY(!m.keyReleased(Qt::Key_Control));
236     QCOMPARE(a->m_beginIndex, -1);
237 
238 
239     // There is no Shift+LB shortcut
240     QVERIFY(!m.buttonPressed(Qt::LeftButton, &mouseEvent));
241     QCOMPARE(a->m_beginIndex, -1);
242 
243     QVERIFY(!m.buttonReleased(Qt::LeftButton, &mouseEvent));
244     QCOMPARE(a->m_beginIndex, -1);
245 
246 
247     // But there *is* Shift+RB shortcut
248     QVERIFY(m.buttonPressed(Qt::RightButton, &mouseEvent));
249     QCOMPARE(a->m_beginIndex, 12);
250     QCOMPARE(a->m_ended, false);
251     QCOMPARE(a->m_beginNonNull, true);
252     QCOMPARE(a->m_endNonNull, false);
253     a->reset();
254 
255     QVERIFY(m.buttonReleased(Qt::RightButton, &mouseEvent));
256     QCOMPARE(a->m_beginIndex, -1);
257     QCOMPARE(a->m_ended, true);
258     QCOMPARE(a->m_beginNonNull, false);
259     QCOMPARE(a->m_endNonNull, true);
260     a->reset();
261 
262 
263     // Check that Shift+Enter still works
264     QVERIFY(m.keyPressed(Qt::Key_Enter));
265     QCOMPARE(a->m_beginIndex, 10);
266     QCOMPARE(a->m_ended, true);
267     QCOMPARE(a->m_beginNonNull, false);
268     QCOMPARE(a->m_endNonNull, false);
269     a->reset();
270 
271     m.leaveEvent();
272 }
273 
testReleaseUnnecessaryModifiers()274 void KisInputManagerTest::testReleaseUnnecessaryModifiers()
275 {
276     KisShortcutMatcher m;
277     m.enterEvent();
278 
279     TestingAction *a = new TestingAction();
280 
281     m.addShortcut(
282         createStrokeShortcut(a, 13,
283                              QSet<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
284                              Qt::LeftButton));
285 
286     // Test event with random values
287     QMouseEvent mouseEvent(QEvent::MouseMove, QPoint(),
288                            Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
289 
290     // Press Ctrl+Shift
291     QVERIFY(!m.keyPressed(Qt::Key_Shift));
292     QCOMPARE(a->m_beginIndex, -1);
293 
294     QVERIFY(!m.keyPressed(Qt::Key_Control));
295     QCOMPARE(a->m_beginIndex, -1);
296 
297     // Complete Ctrl+Shift+LB shortcut
298     QVERIFY(m.buttonPressed(Qt::LeftButton, &mouseEvent));
299     QCOMPARE(a->m_beginIndex, 13);
300     QCOMPARE(a->m_ended, false);
301     a->reset();
302 
303     // Release Ctrl
304     QVERIFY(!m.keyReleased(Qt::Key_Control));
305     QCOMPARE(a->m_beginIndex, -1);
306     QCOMPARE(a->m_ended, false);
307 
308     // Release Shift
309     QVERIFY(!m.keyReleased(Qt::Key_Shift));
310     QCOMPARE(a->m_beginIndex, -1);
311     QCOMPARE(a->m_ended, false);
312 
313     // Release LB, now it should end
314     QVERIFY(m.buttonReleased(Qt::LeftButton, &mouseEvent));
315     QCOMPARE(a->m_beginIndex, -1);
316     QCOMPARE(a->m_ended, true);
317     a->reset();
318 
319     m.leaveEvent();
320 }
321 
testMouseMoves()322 void KisInputManagerTest::testMouseMoves()
323 {
324     KisShortcutMatcher m;
325     m.enterEvent();
326 
327     TestingAction *a = new TestingAction();
328 
329     m.addShortcut(
330         createStrokeShortcut(a, 13,
331                              QSet<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
332                              Qt::LeftButton));
333 
334     // Test event with random values
335     QMouseEvent mouseEvent(QEvent::MouseMove, QPoint(),
336                            Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
337 
338 
339     // Press Ctrl+Shift
340     QVERIFY(!m.keyPressed(Qt::Key_Shift));
341     QCOMPARE(a->m_beginIndex, -1);
342 
343     QVERIFY(!m.keyPressed(Qt::Key_Control));
344     QCOMPARE(a->m_beginIndex, -1);
345 
346     QVERIFY(!m.pointerMoved(&mouseEvent));
347     QCOMPARE(a->m_gotInput, false);
348 
349     // Complete Ctrl+Shift+LB shortcut
350     QVERIFY(m.buttonPressed(Qt::LeftButton, &mouseEvent));
351     QCOMPARE(a->m_beginIndex, 13);
352     QCOMPARE(a->m_ended, false);
353     QCOMPARE(a->m_gotInput, false);
354     a->reset();
355 
356     QVERIFY(m.pointerMoved(&mouseEvent));
357     QCOMPARE(a->m_gotInput, true);
358     a->reset();
359 
360     // Release Ctrl
361     QVERIFY(!m.keyReleased(Qt::Key_Control));
362     QCOMPARE(a->m_beginIndex, -1);
363     QCOMPARE(a->m_ended, false);
364     QCOMPARE(a->m_gotInput, false);
365 
366     // Release Shift
367     QVERIFY(!m.keyReleased(Qt::Key_Shift));
368     QCOMPARE(a->m_beginIndex, -1);
369     QCOMPARE(a->m_ended, false);
370 
371     // Release LB, now it should end
372     QVERIFY(m.buttonReleased(Qt::LeftButton, &mouseEvent));
373     QCOMPARE(a->m_beginIndex, -1);
374     QCOMPARE(a->m_ended, true);
375     a->reset();
376 
377     m.leaveEvent();
378 }
379 
380 #include "../input/wintab/kis_incremental_average.h"
381 
testIncrementalAverage()382 void KisInputManagerTest::testIncrementalAverage()
383 {
384     KisIncrementalAverage avg(3);
385 
386     QCOMPARE(avg.pushThrough(10), 10);
387     QCOMPARE(avg.pushThrough(20), 13);
388     QCOMPARE(avg.pushThrough(30), 20);
389     QCOMPARE(avg.pushThrough(30), 26);
390     QCOMPARE(avg.pushThrough(30), 30);
391 
392 }
393 
394 QTEST_MAIN(KisInputManagerTest)
395