mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-01 13:36:48 +08:00
141 lines
4.2 KiB
C++
141 lines
4.2 KiB
C++
/* Copyright (C) 2014
|
|
* swift Project Community / Contributors
|
|
*
|
|
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
|
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
|
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
|
* contained in the LICENSE file.
|
|
*/
|
|
|
|
#include "blackmisc/logmessage.h"
|
|
#include "joysticklinux.h"
|
|
#include <QFile>
|
|
#include <QFileSystemWatcher>
|
|
#include <QSocketNotifier>
|
|
#include <QSignalMapper>
|
|
#include <linux/joystick.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
|
|
using namespace BlackMisc;
|
|
using namespace BlackMisc::Input;
|
|
|
|
namespace
|
|
{
|
|
inline QString inputDevicesDir()
|
|
{
|
|
return QStringLiteral("/dev/input/");
|
|
}
|
|
}
|
|
|
|
namespace BlackInput
|
|
{
|
|
CJoystickLinux::CJoystickLinux(QObject *parent) :
|
|
IJoystick(parent),
|
|
m_mapper(new QSignalMapper(this)),
|
|
m_inputWatcher(new QFileSystemWatcher(this))
|
|
{
|
|
connect(m_mapper, static_cast<void (QSignalMapper::*)(QObject *)>(&QSignalMapper::mapped), this, &CJoystickLinux::ps_readInput);
|
|
|
|
m_inputWatcher->addPath(inputDevicesDir());
|
|
connect(m_inputWatcher, &QFileSystemWatcher::directoryChanged, this, &CJoystickLinux::ps_directoryChanged);
|
|
ps_directoryChanged(inputDevicesDir());
|
|
}
|
|
|
|
void CJoystickLinux::cleanupJoysticks()
|
|
{
|
|
for (auto it = m_joysticks.begin(); it != m_joysticks.end();)
|
|
{
|
|
if (!it.value()->exists())
|
|
{
|
|
it.value()->deleteLater();
|
|
it = m_joysticks.erase(it);
|
|
}
|
|
else
|
|
{
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CJoystickLinux::addJoystickDevice(const QString &path)
|
|
{
|
|
Q_ASSERT(!m_joysticks.contains(path));
|
|
|
|
QFile *joystick = new QFile(path, this);
|
|
if (joystick->open(QIODevice::ReadOnly))
|
|
{
|
|
char name[256];
|
|
if (ioctl(joystick->handle(), JSIOCGNAME(sizeof(name)), name) < 0)
|
|
{
|
|
strncpy(name, "Unknown", sizeof(name));
|
|
}
|
|
|
|
CLogMessage(this).info("Found joystick: %1") << name;
|
|
|
|
fcntl(joystick->handle(), F_SETFL, O_NONBLOCK);
|
|
|
|
/* Forward */
|
|
struct js_event event;
|
|
while (joystick->read(reinterpret_cast<char *>(&event), sizeof(event)) == sizeof(event)) {}
|
|
|
|
QSocketNotifier *notifier = new QSocketNotifier(joystick->handle(), QSocketNotifier::Read, joystick);
|
|
m_mapper->setMapping(notifier, joystick);
|
|
connect(notifier, &QSocketNotifier::activated, m_mapper, static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map));
|
|
notifier->setEnabled(true);
|
|
|
|
m_joysticks.insert(path, joystick);
|
|
}
|
|
else
|
|
{
|
|
joystick->deleteLater();
|
|
}
|
|
}
|
|
|
|
void CJoystickLinux::ps_directoryChanged(QString path)
|
|
{
|
|
cleanupJoysticks();
|
|
|
|
QDir dir(path, QLatin1String("js*"), 0, QDir::System);
|
|
for (const auto &entry : dir.entryInfoList())
|
|
{
|
|
QString f = entry.absoluteFilePath();
|
|
if (!m_joysticks.contains(f))
|
|
{
|
|
addJoystickDevice(f);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CJoystickLinux::ps_readInput(QObject *object)
|
|
{
|
|
QFile *joystick = qobject_cast<QFile *>(object);
|
|
Q_ASSERT(joystick);
|
|
|
|
|
|
struct js_event event;
|
|
while (joystick->read(reinterpret_cast<char *>(&event), sizeof(event)) == sizeof(event))
|
|
{
|
|
BlackMisc::Input::CHotkeyCombination oldCombination(m_buttonCombination);
|
|
switch (event.type & ~JS_EVENT_INIT)
|
|
{
|
|
case JS_EVENT_BUTTON:
|
|
if (event.value)
|
|
{
|
|
m_buttonCombination.addJoystickButton(event.number);
|
|
}
|
|
else
|
|
{
|
|
m_buttonCombination.removeJoystickButton(event.number);
|
|
}
|
|
|
|
if (oldCombination != m_buttonCombination)
|
|
{
|
|
emit buttonCombinationChanged(m_buttonCombination);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} // namespace BlackInput
|