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