1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Gamepad module
7 **
8 ** $QT_BEGIN_LICENSE:LGPL3$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or later as published by the Free
28 ** Software Foundation and appearing in the file LICENSE.GPL included in
29 ** the packaging of this file. Please review the following information to
30 ** ensure the GNU General Public License version 2.0 requirements will be
31 ** met: http://www.gnu.org/licenses/gpl-2.0.html.
32 **
33 ** $QT_END_LICENSE$
34 **
35 ****************************************************************************/
36 
37 #include "qgamepadkeynavigation.h"
38 #include <QtGui/QKeyEvent>
39 #include <QtGui/QGuiApplication>
40 #include <QtGui/QWindow>
41 #include <QtGamepad/QGamepad>
42 
43 #include <private/qobject_p.h>
44 
45 QT_BEGIN_NAMESPACE
46 
47 class QGamepadKeyNavigationPrivate : public QObjectPrivate
48 {
49     Q_DECLARE_PUBLIC(QGamepadKeyNavigation)
50 public:
QGamepadKeyNavigationPrivate()51     QGamepadKeyNavigationPrivate()
52         : active(true)
53         , gamepad(nullptr)
54         , buttonL2Pressed(false)
55         , buttonR2Pressed(false)
56     {
57     }
58 
59     void sendGeneratedKeyEvent(QKeyEvent *event);
60 
61     bool active;
62     QGamepad *gamepad;
63     QGamepadManager *gamepadManger;
64     bool buttonL2Pressed;
65     bool buttonR2Pressed;
66     QMap<QGamepadManager::GamepadButton, Qt::Key> keyMapping;
67 
68     void _q_processGamepadButtonPressEvent(int index, QGamepadManager::GamepadButton button, double value);
69     void _q_processGamepadButtonReleaseEvent(int index, QGamepadManager::GamepadButton button);
70 };
71 
sendGeneratedKeyEvent(QKeyEvent * event)72 void QGamepadKeyNavigationPrivate::sendGeneratedKeyEvent(QKeyEvent *event)
73 {
74     if (!active) {
75         delete event;
76         return;
77     }
78     const QGuiApplication *app = qApp;
79     QWindow *focusWindow = app ? app->focusWindow() : nullptr;
80     if (focusWindow)
81         QGuiApplication::sendEvent(focusWindow, event);
82 }
83 
_q_processGamepadButtonPressEvent(int index,QGamepadManager::GamepadButton button,double value)84 void QGamepadKeyNavigationPrivate::_q_processGamepadButtonPressEvent(int index, QGamepadManager::GamepadButton button, double value)
85 {
86     Q_UNUSED(value)
87     //If a gamepad has been set then, only use the events of that gamepad
88     if (gamepad && gamepad->deviceId() != index)
89         return;
90 
91     //Trigger buttons are a special case as they get multiple press events as the value changes
92     if (button == QGamepadManager::ButtonL2 && buttonL2Pressed)
93         return;
94     else
95         buttonL2Pressed = true;
96     if (button == QGamepadManager::ButtonR2 && buttonR2Pressed)
97         return;
98     else
99         buttonR2Pressed = true;
100 
101     QKeyEvent *event = new QKeyEvent(QEvent::KeyPress, keyMapping[button], Qt::NoModifier);
102     sendGeneratedKeyEvent(event);
103 }
104 
_q_processGamepadButtonReleaseEvent(int index,QGamepadManager::GamepadButton button)105 void QGamepadKeyNavigationPrivate::_q_processGamepadButtonReleaseEvent(int index, QGamepadManager::GamepadButton button)
106 {
107     //If a gamepad has been set then, only use the events of that gamepad
108     if (gamepad && gamepad->deviceId() != index)
109         return;
110 
111     //Free the trigger buttons if necessary
112     if (button == QGamepadManager::ButtonL2)
113         buttonL2Pressed = false;
114     if (button == QGamepadManager::ButtonR2)
115         buttonR2Pressed = false;
116 
117     QKeyEvent *event = new QKeyEvent(QEvent::KeyRelease, keyMapping[button], Qt::NoModifier);
118     sendGeneratedKeyEvent(event);
119 }
120 
121 /*!
122    \class QGamepadKeyNavigation
123    \inmodule QtGamepad
124    \brief Provides support for keyboard events triggered by gamepads.
125 
126    QGamepadKeyNavigation provides support for keyboard events triggered by
127    gamepads.
128  */
129 
130 /*!
131  * Constructs a QGamepadNavigation object with the given \a parent.
132  */
133 
QGamepadKeyNavigation(QObject * parent)134 QGamepadKeyNavigation::QGamepadKeyNavigation(QObject *parent)
135     : QObject(*new QGamepadKeyNavigationPrivate(), parent)
136 {
137     Q_D(QGamepadKeyNavigation);
138     d->gamepadManger = QGamepadManager::instance();
139 
140     //Default keymap
141     d->keyMapping.insert(QGamepadManager::ButtonUp, Qt::Key_Up);
142     d->keyMapping.insert(QGamepadManager::ButtonDown, Qt::Key_Down);
143     d->keyMapping.insert(QGamepadManager::ButtonLeft, Qt::Key_Left);
144     d->keyMapping.insert(QGamepadManager::ButtonRight, Qt::Key_Right);
145     d->keyMapping.insert(QGamepadManager::ButtonA, Qt::Key_Return);
146     d->keyMapping.insert(QGamepadManager::ButtonB, Qt::Key_Back);
147     d->keyMapping.insert(QGamepadManager::ButtonX, Qt::Key_Back);
148     d->keyMapping.insert(QGamepadManager::ButtonY, Qt::Key_Back);
149     d->keyMapping.insert(QGamepadManager::ButtonSelect, Qt::Key_Back);
150     d->keyMapping.insert(QGamepadManager::ButtonStart, Qt::Key_Return);
151     d->keyMapping.insert(QGamepadManager::ButtonGuide, Qt::Key_Back);
152     d->keyMapping.insert(QGamepadManager::ButtonL1, Qt::Key_Back);
153     d->keyMapping.insert(QGamepadManager::ButtonR1, Qt::Key_Forward);
154     d->keyMapping.insert(QGamepadManager::ButtonL2, Qt::Key_Back);
155     d->keyMapping.insert(QGamepadManager::ButtonR2, Qt::Key_Forward);
156     d->keyMapping.insert(QGamepadManager::ButtonL3, Qt::Key_Back);
157     d->keyMapping.insert(QGamepadManager::ButtonR3, Qt::Key_Forward);
158 
159     connect(d->gamepadManger, SIGNAL(gamepadButtonPressEvent(int,QGamepadManager::GamepadButton,double)),
160             this, SLOT(_q_processGamepadButtonPressEvent(int,QGamepadManager::GamepadButton,double)));
161     connect(d->gamepadManger, SIGNAL(gamepadButtonReleaseEvent(int,QGamepadManager::GamepadButton)),
162             this, SLOT(_q_processGamepadButtonReleaseEvent(int,QGamepadManager::GamepadButton)));
163 }
164 
165 /*!
166  * Returns whether key navigation on the gamepad is active or not.
167 */
active() const168 bool QGamepadKeyNavigation::active() const
169 {
170     Q_D(const QGamepadKeyNavigation);
171     return d->active;
172 }
173 
174 /*!
175  * Returns a pointer the current QGamepad
176  */
gamepad() const177 QGamepad *QGamepadKeyNavigation::gamepad() const
178 {
179     Q_D(const QGamepadKeyNavigation);
180     return d->gamepad;
181 }
182 
183 /*!
184  * Returns the key mapping of the Up button.
185  */
upKey() const186 Qt::Key QGamepadKeyNavigation::upKey() const
187 {
188     Q_D(const QGamepadKeyNavigation);
189     return d->keyMapping[QGamepadManager::ButtonUp];
190 }
191 
192 /*!
193  * Returns the key mapping of the Down button.
194  */
downKey() const195 Qt::Key QGamepadKeyNavigation::downKey() const
196 {
197     Q_D(const QGamepadKeyNavigation);
198     return d->keyMapping[QGamepadManager::ButtonDown];
199 }
200 
201 /*!
202  * Returns the key mapping of the Left button.
203  */
leftKey() const204 Qt::Key QGamepadKeyNavigation::leftKey() const
205 {
206     Q_D(const QGamepadKeyNavigation);
207     return d->keyMapping[QGamepadManager::ButtonLeft];
208 }
209 
210 /*!
211  * Returns the key mapping of the Right button.
212  */
rightKey() const213 Qt::Key QGamepadKeyNavigation::rightKey() const
214 {
215     Q_D(const QGamepadKeyNavigation);
216     return d->keyMapping[QGamepadManager::ButtonRight];
217 }
218 
219 /*!
220  * Returns the key mapping of A button.
221  */
buttonAKey() const222 Qt::Key QGamepadKeyNavigation::buttonAKey() const
223 {
224     Q_D(const QGamepadKeyNavigation);
225     return d->keyMapping[QGamepadManager::ButtonA];
226 }
227 
228 /*!
229  * Returns the key mapping of the B button.
230  */
buttonBKey() const231 Qt::Key QGamepadKeyNavigation::buttonBKey() const
232 {
233     Q_D(const QGamepadKeyNavigation);
234     return d->keyMapping[QGamepadManager::ButtonB];
235 }
236 
237 /*!
238  * Returns the key mapping of the X button.
239  */
buttonXKey() const240 Qt::Key QGamepadKeyNavigation::buttonXKey() const
241 {
242     Q_D(const QGamepadKeyNavigation);
243     return d->keyMapping[QGamepadManager::ButtonX];
244 }
245 
246 /*!
247  * Returns the key mapping of the Y button.
248  */
buttonYKey() const249 Qt::Key QGamepadKeyNavigation::buttonYKey() const
250 {
251     Q_D(const QGamepadKeyNavigation);
252     return d->keyMapping[QGamepadManager::ButtonY];
253 }
254 
255 /*!
256  * Returns the key mapping of the Select button.
257  */
buttonSelectKey() const258 Qt::Key QGamepadKeyNavigation::buttonSelectKey() const
259 {
260     Q_D(const QGamepadKeyNavigation);
261     return d->keyMapping[QGamepadManager::ButtonSelect];
262 }
263 
264 /*!
265  * Returns the key mapping of the Start button.
266  */
buttonStartKey() const267 Qt::Key QGamepadKeyNavigation::buttonStartKey() const
268 {
269     Q_D(const QGamepadKeyNavigation);
270     return d->keyMapping[QGamepadManager::ButtonStart];
271 }
272 
273 /*!
274  * Returns the key mapping of the Guide button.
275  */
buttonGuideKey() const276 Qt::Key QGamepadKeyNavigation::buttonGuideKey() const
277 {
278     Q_D(const QGamepadKeyNavigation);
279     return d->keyMapping[QGamepadManager::ButtonGuide];
280 }
281 
282 /*!
283  * Returns the key mapping of the left shoulder button.
284  */
buttonL1Key() const285 Qt::Key QGamepadKeyNavigation::buttonL1Key() const
286 {
287     Q_D(const QGamepadKeyNavigation);
288     return d->keyMapping[QGamepadManager::ButtonL1];
289 }
290 
291 /*!
292  * Returns the key mapping of the Right shoulder button.
293  */
buttonR1Key() const294 Qt::Key QGamepadKeyNavigation::buttonR1Key() const
295 {
296     Q_D(const QGamepadKeyNavigation);
297     return d->keyMapping[QGamepadManager::ButtonL2];
298 }
299 
300 /*!
301  * Returns the key mapping of the left trigger button.
302  */
buttonL2Key() const303 Qt::Key QGamepadKeyNavigation::buttonL2Key() const
304 {
305     Q_D(const QGamepadKeyNavigation);
306     return d->keyMapping[QGamepadManager::ButtonL2];
307 }
308 
309 /*!
310  * Returns the key mapping of the Right trigger button.
311  */
buttonR2Key() const312 Qt::Key QGamepadKeyNavigation::buttonR2Key() const
313 {
314     Q_D(const QGamepadKeyNavigation);
315     return d->keyMapping[QGamepadManager::ButtonL2];
316 }
317 
318 /*!
319  * Returns the key mapping of the left stick button.
320  */
buttonL3Key() const321 Qt::Key QGamepadKeyNavigation::buttonL3Key() const
322 {
323     Q_D(const QGamepadKeyNavigation);
324     return d->keyMapping[QGamepadManager::ButtonL3];
325 }
326 
327 /*!
328  * Returns the key mapping of the right stick button.
329  */
buttonR3Key() const330 Qt::Key QGamepadKeyNavigation::buttonR3Key() const
331 {
332     Q_D(const QGamepadKeyNavigation);
333     return d->keyMapping[QGamepadManager::ButtonL3];
334 }
335 
336 /*!
337  * Activates key navigation if \a isActive is true,
338  * disables it otherwise.
339  */
setActive(bool isActive)340 void QGamepadKeyNavigation::setActive(bool isActive)
341 {
342     Q_D(QGamepadKeyNavigation);
343     if (d->active != isActive) {
344         d->active = isActive;
345         emit activeChanged(isActive);
346     }
347 }
348 
349 /*!
350  * Selects the specified \a gamepad.
351 */
setGamepad(QGamepad * gamepad)352 void QGamepadKeyNavigation::setGamepad(QGamepad *gamepad)
353 {
354     Q_D(QGamepadKeyNavigation);
355     if (d->gamepad != gamepad) {
356         d->gamepad = gamepad;
357         emit gamepadChanged(gamepad);
358     }
359 }
360 
361 /*!
362  * Sets the mapping of the Up button with the
363  * keycode specified in \a key.
364 */
setUpKey(Qt::Key key)365 void QGamepadKeyNavigation::setUpKey(Qt::Key key)
366 {
367     Q_D(QGamepadKeyNavigation);
368     if (d->keyMapping[QGamepadManager::ButtonUp] != key) {
369         d->keyMapping[QGamepadManager::ButtonUp] = key;
370         emit upKeyChanged(key);
371     }
372 }
373 
374 /*!
375  * Sets the mapping of the Down button with the
376  * keycode specified in \a key.
377 */
setDownKey(Qt::Key key)378 void QGamepadKeyNavigation::setDownKey(Qt::Key key)
379 {
380     Q_D(QGamepadKeyNavigation);
381     if (d->keyMapping[QGamepadManager::ButtonDown] != key) {
382         d->keyMapping[QGamepadManager::ButtonDown] = key;
383         emit downKeyChanged(key);
384     }
385 }
386 
387 /*!
388  * Sets the mapping of the Left button with the
389  * keycode specified in \a key.
390 */
setLeftKey(Qt::Key key)391 void QGamepadKeyNavigation::setLeftKey(Qt::Key key)
392 {
393     Q_D(QGamepadKeyNavigation);
394     if (d->keyMapping[QGamepadManager::ButtonLeft] != key) {
395         d->keyMapping[QGamepadManager::ButtonLeft] = key;
396         emit leftKeyChanged(key);
397     }
398 }
399 
400 /*!
401  * Sets the mapping of the Right button with the
402  * keycode specified in \a key.
403 */
setRightKey(Qt::Key key)404 void QGamepadKeyNavigation::setRightKey(Qt::Key key)
405 {
406     Q_D(QGamepadKeyNavigation);
407     if (d->keyMapping[QGamepadManager::ButtonRight] != key) {
408         d->keyMapping[QGamepadManager::ButtonRight] = key;
409         emit rightKeyChanged(key);
410     }
411 }
412 
413 /*!
414  * Sets the mapping of the A button with the keycode
415  * specified in \a key.
416 */
setButtonAKey(Qt::Key key)417 void QGamepadKeyNavigation::setButtonAKey(Qt::Key key)
418 {
419     Q_D(QGamepadKeyNavigation);
420     if (d->keyMapping[QGamepadManager::ButtonA] != key) {
421         d->keyMapping[QGamepadManager::ButtonA] = key;
422         emit buttonAKeyChanged(key);
423     }
424 }
425 
426 /*!
427  * Sets the mapping of the B button with the keycode
428  * specified in \a key.
429 */
setButtonBKey(Qt::Key key)430 void QGamepadKeyNavigation::setButtonBKey(Qt::Key key)
431 {
432     Q_D(QGamepadKeyNavigation);
433     if (d->keyMapping[QGamepadManager::ButtonB] != key) {
434         d->keyMapping[QGamepadManager::ButtonB] = key;
435         emit buttonBKeyChanged(key);
436     }
437 }
438 
439 /*!
440  * Sets the mapping of the X button with the
441  * keycode specified in \a key.
442 */
setButtonXKey(Qt::Key key)443 void QGamepadKeyNavigation::setButtonXKey(Qt::Key key)
444 {
445     Q_D(QGamepadKeyNavigation);
446     if (d->keyMapping[QGamepadManager::ButtonX] != key) {
447         d->keyMapping[QGamepadManager::ButtonX] = key;
448         emit buttonXKeyChanged(key);
449     }
450 }
451 
452 /*!
453  * Sets the mapping of the Y button with the
454  * keycode specified in \a key.
455 */
setButtonYKey(Qt::Key key)456 void QGamepadKeyNavigation::setButtonYKey(Qt::Key key)
457 {
458     Q_D(QGamepadKeyNavigation);
459     if (d->keyMapping[QGamepadManager::ButtonY] != key) {
460         d->keyMapping[QGamepadManager::ButtonY] = key;
461         emit buttonYKeyChanged(key);
462     }
463 }
464 
465 /*!
466  * Sets the mapping of the Select button with the
467  * keycode specified in \a key.
468 */
setButtonSelectKey(Qt::Key key)469 void QGamepadKeyNavigation::setButtonSelectKey(Qt::Key key)
470 {
471     Q_D(QGamepadKeyNavigation);
472     if (d->keyMapping[QGamepadManager::ButtonSelect] != key) {
473         d->keyMapping[QGamepadManager::ButtonSelect] = key;
474         emit buttonSelectKeyChanged(key);
475     }
476 }
477 
478 /*!
479  * Sets the mapping of the Start button with the
480  * keycode specified in \a key.
481 */
setButtonStartKey(Qt::Key key)482 void QGamepadKeyNavigation::setButtonStartKey(Qt::Key key)
483 {
484     Q_D(QGamepadKeyNavigation);
485     if (d->keyMapping[QGamepadManager::ButtonStart] != key) {
486         d->keyMapping[QGamepadManager::ButtonStart] = key;
487         emit buttonStartKeyChanged(key);
488     }
489 }
490 
491 /*!
492  * Sets the mapping of the Guide button with the keycode
493  * specified in \a key.
494 */
setButtonGuideKey(Qt::Key key)495 void QGamepadKeyNavigation::setButtonGuideKey(Qt::Key key)
496 {
497     Q_D(QGamepadKeyNavigation);
498     if (d->keyMapping[QGamepadManager::ButtonGuide] != key) {
499         d->keyMapping[QGamepadManager::ButtonGuide] = key;
500         emit buttonGuideKeyChanged(key);
501     }
502 }
503 
504 /*!
505  * Sets the mapping of the left shoulder button with the
506  * keycode specified in \a key.
507 */
setButtonL1Key(Qt::Key key)508 void QGamepadKeyNavigation::setButtonL1Key(Qt::Key key)
509 {
510     Q_D(QGamepadKeyNavigation);
511     if (d->keyMapping[QGamepadManager::ButtonL1] != key) {
512         d->keyMapping[QGamepadManager::ButtonL1] = key;
513         emit buttonL1KeyChanged(key);
514     }
515 }
516 
517 /*!
518  * Sets the mapping of the right shoulder button with the
519  * keycode specified in \a key.
520 */
setButtonR1Key(Qt::Key key)521 void QGamepadKeyNavigation::setButtonR1Key(Qt::Key key)
522 {
523     Q_D(QGamepadKeyNavigation);
524     if (d->keyMapping[QGamepadManager::ButtonR1] != key) {
525         d->keyMapping[QGamepadManager::ButtonR1] = key;
526         emit buttonR1KeyChanged(key);
527     }
528 }
529 
530 /*!
531  * Sets the mapping of the left trigger button with the
532  * keycode specified in \a key.
533 */
setButtonL2Key(Qt::Key key)534 void QGamepadKeyNavigation::setButtonL2Key(Qt::Key key)
535 {
536     Q_D(QGamepadKeyNavigation);
537     if (d->keyMapping[QGamepadManager::ButtonL2] != key) {
538         d->keyMapping[QGamepadManager::ButtonL2] = key;
539         emit buttonL1KeyChanged(key);
540     }
541 }
542 
543 /*!
544  * Sets the mapping of the right trigger button with the
545  * keycode specified in \a key.
546 */
setButtonR2Key(Qt::Key key)547 void QGamepadKeyNavigation::setButtonR2Key(Qt::Key key)
548 {
549     Q_D(QGamepadKeyNavigation);
550     if (d->keyMapping[QGamepadManager::ButtonR2] != key) {
551         d->keyMapping[QGamepadManager::ButtonR2] = key;
552         emit buttonR1KeyChanged(key);
553     }
554 }
555 
556 /*!
557  * Sets the mapping of the left stick button with the
558  * keycode specified in \a key.
559 */
setButtonL3Key(Qt::Key key)560 void QGamepadKeyNavigation::setButtonL3Key(Qt::Key key)
561 {
562     Q_D(QGamepadKeyNavigation);
563     if (d->keyMapping[QGamepadManager::ButtonL3] != key) {
564         d->keyMapping[QGamepadManager::ButtonL3] = key;
565         emit buttonL1KeyChanged(key);
566     }
567 }
568 
569 /*!
570  * Sets the mapping of the right stick button with the
571  * keycode specified in \a key.
572 */
setButtonR3Key(Qt::Key key)573 void QGamepadKeyNavigation::setButtonR3Key(Qt::Key key)
574 {
575     Q_D(QGamepadKeyNavigation);
576     if (d->keyMapping[QGamepadManager::ButtonR3] != key) {
577         d->keyMapping[QGamepadManager::ButtonR3] = key;
578         emit buttonR1KeyChanged(key);
579     }
580 }
581 
582 QT_END_NAMESPACE
583 
584 #include "moc_qgamepadkeynavigation.cpp"
585