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 "qgamepadmouseitem.h"
38#include <cmath>
39
40#include <QtGamepad/QGamepad>
41#include <QtGui/QWindow>
42#include <QtQuick/QQuickWindow>
43#include <QtGui/QGuiApplication>
44
45QT_BEGIN_NAMESPACE
46
47QGamepadMouseItem::QGamepadMouseItem(QQuickItem *parent)
48 : QQuickItem(parent)
49 , m_active(false)
50 , m_gamepad(nullptr)
51 , m_joystick(QGamepadMouseItem::LeftStick)
52 , m_deadZoneSize(0.1)
53{
54 m_updateTimer.setInterval(16);
55 connect(sender: &m_updateTimer, SIGNAL(timeout()), receiver: this, SLOT(updateMousePostion()));
56}
57
58bool QGamepadMouseItem::active() const
59{
60 return m_active;
61}
62
63QGamepad *QGamepadMouseItem::gamepad() const
64{
65 return m_gamepad;
66}
67
68QGamepadMouseItem::GamepadJoystick QGamepadMouseItem::joystick() const
69{
70 return m_joystick;
71}
72
73double QGamepadMouseItem::deadZoneSize() const
74{
75 return m_deadZoneSize;
76}
77
78QPointF QGamepadMouseItem::mousePosition() const
79{
80 return m_mousePosition;
81}
82
83void QGamepadMouseItem::setActive(bool arg)
84{
85 if (m_active != arg) {
86 m_active = arg;
87 if (m_active) {
88 m_deltaTimer.start();
89 m_updateTimer.start();
90 } else {
91 m_updateTimer.stop();
92 m_deltaTimer.invalidate();
93 }
94 emit activeChanged(isActive: arg);
95 }
96}
97
98void QGamepadMouseItem::setGamepad(QGamepad *gamepad)
99{
100 if (m_gamepad != gamepad) {
101 m_gamepad = gamepad;
102 emit gamepadChanged(gamepad);
103 }
104}
105
106void QGamepadMouseItem::setJoystick(QGamepadMouseItem::GamepadJoystick joystick)
107{
108 if (m_joystick != joystick) {
109 m_joystick = joystick;
110 emit joystickChanged(joystick);
111 }
112}
113
114void QGamepadMouseItem::setDeadZoneSize(double size)
115{
116 if (m_deadZoneSize != size) {
117 m_deadZoneSize = size;
118 emit deadZoneSizeChanged(size);
119 }
120}
121
122void QGamepadMouseItem::mouseButtonPressed(int button)
123{
124 processMouseButtonEvent(isPressed: true, button: (Qt::MouseButton)button);
125}
126
127void QGamepadMouseItem::mouseButtonReleased(int button)
128{
129 processMouseButtonEvent(isPressed: false, button: (Qt::MouseButton)button);
130}
131
132void QGamepadMouseItem::updateMousePostion()
133{
134 //Get the delta from the last call
135 qint64 delta = m_deltaTimer.restart();
136
137 //Don't bother when there is not gamepad to read from
138 if (!m_gamepad || !m_gamepad->isConnected())
139 return;
140
141 double xVelocity = 0.0;
142 double yVelocity = 0.0;
143
144 if (m_joystick == QGamepadMouseItem::LeftStick) {
145 xVelocity = m_gamepad->axisLeftX();
146 yVelocity = m_gamepad->axisLeftY();
147 } else if (m_joystick == QGamepadMouseItem::RightStick) {
148 xVelocity = m_gamepad->axisRightX();
149 yVelocity = m_gamepad->axisRightY();
150 } else { //The greatest of both
151 if (std::abs(x: m_gamepad->axisLeftX()) > std::abs(x: m_gamepad->axisRightX()))
152 xVelocity = m_gamepad->axisLeftX();
153 else
154 xVelocity = m_gamepad->axisRightX();
155 if (std::abs(x: m_gamepad->axisLeftY()) > std::abs(x: m_gamepad->axisRightY()))
156 yVelocity = m_gamepad->axisLeftY();
157 else
158 yVelocity = m_gamepad->axisRightY();
159 }
160
161 //Check for deadzone limits]
162 if (std::abs(x: xVelocity) < m_deadZoneSize)
163 xVelocity = 0.0;
164 if (std::abs(x: yVelocity) < m_deadZoneSize)
165 yVelocity = 0.0;
166 if (xVelocity == 0.0 && yVelocity == 0.0)
167 return;
168
169 double newXPosition = m_mousePosition.x() + xVelocity * delta;
170 double newYPosition = m_mousePosition.y() + yVelocity * delta;
171 //Check bounds
172 if (newXPosition < 0)
173 newXPosition = 0;
174 else if (newXPosition > width())
175 newXPosition = width();
176
177 if (newYPosition < 0)
178 newYPosition = 0;
179 else if (newYPosition > height())
180 newYPosition = height();
181
182 m_mousePosition = QPointF(newXPosition, newYPosition);
183 emit mousePositionChanged(position: m_mousePosition);
184}
185
186void QGamepadMouseItem::processMouseMoveEvent(QPointF position)
187{
188 QMouseEvent *mouseEvent = new QMouseEvent(QEvent::MouseMove, mapToScene(point: position), Qt::NoButton, m_mouseButtons, Qt::NoModifier);
189 sendGeneratedMouseEvent(event: mouseEvent);
190}
191
192void QGamepadMouseItem::processMouseButtonEvent(bool isPressed, Qt::MouseButton button)
193{
194 QMouseEvent *event;
195 if (isPressed) {
196 m_mouseButtons |= button;
197 event = new QMouseEvent(QEvent::MouseButtonPress, mapToScene(point: m_mousePosition), button, m_mouseButtons, Qt::NoModifier);
198 } else {
199 m_mouseButtons ^= button;
200 event = new QMouseEvent(QEvent::MouseButtonRelease, mapToScene(point: m_mousePosition), button, m_mouseButtons, Qt::NoModifier);
201 }
202
203 sendGeneratedMouseEvent(event);
204}
205
206void QGamepadMouseItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
207{
208 QQuickItem::geometryChanged(newGeometry, oldGeometry);
209
210 m_mousePosition = newGeometry.center();
211}
212
213void QGamepadMouseItem::sendGeneratedMouseEvent(QMouseEvent *event)
214{
215 if (!m_active || !this->window()) {
216 delete event;
217 return;
218 }
219
220 QWindow *window = qobject_cast<QWindow*>(o: this->window());
221 if (window)
222 QGuiApplication::sendEvent(receiver: window, event);
223}
224
225QT_END_NAMESPACE
226

source code of qtgamepad/src/imports/gamepad/qgamepadmouseitem.cpp