/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the Qt Gamepad module ** ** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPLv3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or later as published by the Free ** Software Foundation and appearing in the file LICENSE.GPL included in ** the packaging of this file. Please review the following information to ** ensure the GNU General Public License version 2.0 requirements will be ** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qgamepadmouseitem.h" #include #include #include #include #include QT_BEGIN_NAMESPACE QGamepadMouseItem::QGamepadMouseItem(QQuickItem *parent) : QQuickItem(parent) , m_active(false) , m_gamepad(nullptr) , m_joystick(QGamepadMouseItem::LeftStick) , m_deadZoneSize(0.1) { m_updateTimer.setInterval(16); connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateMousePostion())); } bool QGamepadMouseItem::active() const { return m_active; } QGamepad *QGamepadMouseItem::gamepad() const { return m_gamepad; } QGamepadMouseItem::GamepadJoystick QGamepadMouseItem::joystick() const { return m_joystick; } double QGamepadMouseItem::deadZoneSize() const { return m_deadZoneSize; } QPointF QGamepadMouseItem::mousePosition() const { return m_mousePosition; } void QGamepadMouseItem::setActive(bool arg) { if (m_active != arg) { m_active = arg; if (m_active) { m_deltaTimer.start(); m_updateTimer.start(); } else { m_updateTimer.stop(); m_deltaTimer.invalidate(); } emit activeChanged(arg); } } void QGamepadMouseItem::setGamepad(QGamepad *gamepad) { if (m_gamepad != gamepad) { m_gamepad = gamepad; emit gamepadChanged(gamepad); } } void QGamepadMouseItem::setJoystick(QGamepadMouseItem::GamepadJoystick joystick) { if (m_joystick != joystick) { m_joystick = joystick; emit joystickChanged(joystick); } } void QGamepadMouseItem::setDeadZoneSize(double size) { if (m_deadZoneSize != size) { m_deadZoneSize = size; emit deadZoneSizeChanged(size); } } void QGamepadMouseItem::mouseButtonPressed(int button) { processMouseButtonEvent(true, (Qt::MouseButton)button); } void QGamepadMouseItem::mouseButtonReleased(int button) { processMouseButtonEvent(false, (Qt::MouseButton)button); } void QGamepadMouseItem::updateMousePostion() { // Get the delta from the last call qint64 delta = m_deltaTimer.restart(); // Don't bother when there is not gamepad to read from if (!m_gamepad || !m_gamepad->isConnected()) return; double xVelocity = 0.0; double yVelocity = 0.0; if (m_joystick == QGamepadMouseItem::LeftStick) { xVelocity = m_gamepad->axisLeftX(); yVelocity = m_gamepad->axisLeftY(); } else if (m_joystick == QGamepadMouseItem::RightStick) { xVelocity = m_gamepad->axisRightX(); yVelocity = m_gamepad->axisRightY(); } else { // The greatest of both if (std::abs(m_gamepad->axisLeftX()) > std::abs(m_gamepad->axisRightX())) xVelocity = m_gamepad->axisLeftX(); else xVelocity = m_gamepad->axisRightX(); if (std::abs(m_gamepad->axisLeftY()) > std::abs(m_gamepad->axisRightY())) yVelocity = m_gamepad->axisLeftY(); else yVelocity = m_gamepad->axisRightY(); } // Check for deadzone limits] if (std::abs(xVelocity) < m_deadZoneSize) xVelocity = 0.0; if (std::abs(yVelocity) < m_deadZoneSize) yVelocity = 0.0; if (xVelocity == 0.0 && yVelocity == 0.0) return; double newXPosition = m_mousePosition.x() + xVelocity * delta; double newYPosition = m_mousePosition.y() + yVelocity * delta; // Check bounds if (newXPosition < 0) newXPosition = 0; else if (newXPosition > width()) newXPosition = width(); if (newYPosition < 0) newYPosition = 0; else if (newYPosition > height()) newYPosition = height(); m_mousePosition = QPointF(newXPosition, newYPosition); emit mousePositionChanged(m_mousePosition); } void QGamepadMouseItem::processMouseMoveEvent(QPointF position) { QMouseEvent *mouseEvent = new QMouseEvent(QEvent::MouseMove, mapToScene(position), Qt::NoButton, m_mouseButtons, Qt::NoModifier); sendGeneratedMouseEvent(mouseEvent); } void QGamepadMouseItem::processMouseButtonEvent(bool isPressed, Qt::MouseButton button) { QMouseEvent *event; if (isPressed) { m_mouseButtons |= button; event = new QMouseEvent(QEvent::MouseButtonPress, mapToScene(m_mousePosition), button, m_mouseButtons, Qt::NoModifier); } else { m_mouseButtons ^= button; event = new QMouseEvent(QEvent::MouseButtonRelease, mapToScene(m_mousePosition), button, m_mouseButtons, Qt::NoModifier); } sendGeneratedMouseEvent(event); } void QGamepadMouseItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { QQuickItem::geometryChanged(newGeometry, oldGeometry); m_mousePosition = newGeometry.center(); } void QGamepadMouseItem::sendGeneratedMouseEvent(QMouseEvent *event) { if (!m_active || !this->window()) { delete event; return; } QWindow *window = qobject_cast(this->window()); if (window) QGuiApplication::sendEvent(window, event); } QT_END_NAMESPACE