Files
pilotclient/src/blackcore/inputmanager.cpp
Roland Winklmeier 832082c5bc Delay creating input devices to when required
Every first call to CInputManager::instance() was automatically creating
the low level input devices. This was not always desired and therefore
creation is now explicit via function.
Unit tests do not need the devices created. In contrast, Windows unit tests
failed since Windows didn't like the Jenkins service childs to allocate
DInput devices.

T391
2018-10-07 16:17:28 +02:00

179 lines
5.6 KiB
C++

/* Copyright (C) 2013
* 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 "blackcore/inputmanager.h"
#include "blackmisc/compare.h"
#include "blackmisc/dictionary.h"
#include "blackmisc/input/actionhotkey.h"
#include "blackmisc/sequence.h"
#include <limits.h>
#include <QtGlobal>
// clazy:excludeall=detaching-member
using namespace BlackInput;
using namespace BlackMisc;
using namespace BlackMisc::Input;
namespace BlackCore
{
CInputManager::CInputManager(QObject *parent) :
QObject(parent)
{
reloadHotkeySettings();
}
CInputManager *CInputManager::instance()
{
static CInputManager instance;
return &instance;
}
void CInputManager::registerAction(const QString &action, const QPixmap &icon)
{
if (!m_availableActions.contains(action))
{
m_availableActions.insert(action, icon);
emit hotkeyActionRegistered({ action });
}
}
void CInputManager::registerRemoteActions(const QStringList &actions)
{
for (const auto &action : actions)
{
if (!m_availableActions.contains(action))
{
m_availableActions.insert(action, {});
emit hotkeyActionRegistered({ action });
}
}
}
void CInputManager::unbind(int index)
{
auto info = std::find_if(m_boundActions.begin(), m_boundActions.end(), [index](const BindInfo & info) { return info.m_index == index; });
if (info != m_boundActions.end())
{
m_boundActions.erase(info);
}
}
void CInputManager::reloadHotkeySettings()
{
m_configuredActions.clear();
for (const CActionHotkey &actionHotkey : m_actionHotkeys.getThreadLocal())
{
if (!actionHotkey.getApplicableMachine().isFromLocalMachine()) { continue; }
CHotkeyCombination combination = actionHotkey.getCombination();
if (combination.isEmpty()) continue;
m_configuredActions.insert(combination, actionHotkey.getAction());
}
}
void CInputManager::processKeyCombinationChanged(const CHotkeyCombination &combination)
{
// Merge in the joystick part
CHotkeyCombination copy(combination);
copy.setJoystickButtons(m_lastCombination.getJoystickButtons());
processCombination(copy);
}
void CInputManager::processButtonCombinationChanged(const CHotkeyCombination &combination)
{
// Merge in the keyboard keys
CHotkeyCombination copy(combination);
copy.setKeyboardKeys(m_lastCombination.getKeyboardKeys());
processCombination(copy);
}
void CInputManager::startCapture()
{
m_captureActive = true;
m_capturedCombination = {};
}
void CInputManager::callFunctionsBy(const QString &action, bool isKeyDown)
{
if (action.isEmpty()) { return; }
if (m_actionRelayingEnabled) emit remoteActionFromLocal(action, isKeyDown);
for (const auto &boundAction : as_const(m_boundActions))
{
if (boundAction.m_action == action)
{
boundAction.m_function(isKeyDown);
}
}
}
void CInputManager::triggerKey(const CHotkeyCombination &combination, bool isPressed)
{
Q_UNUSED(isPressed)
QString previousAction = m_configuredActions.value(m_lastCombination);
QString action = m_configuredActions.value(combination);
callFunctionsBy(previousAction, false);
callFunctionsBy(action, true);
m_lastCombination = combination;
}
void CInputManager::createDevices()
{
m_keyboard = IKeyboard::create(this);
m_joystick = IJoystick::create(this);
connect(m_keyboard.get(), &IKeyboard::keyCombinationChanged, this, &CInputManager::processKeyCombinationChanged, Qt::QueuedConnection);
connect(m_joystick.get(), &IJoystick::buttonCombinationChanged, this, &CInputManager::processButtonCombinationChanged, Qt::QueuedConnection);
}
void CInputManager::releaseDevices()
{
m_keyboard.reset();
m_joystick.reset();
}
int CInputManager::bindImpl(const QString &action, QObject *receiver, std::function<void (bool)> function)
{
static int index = 0;
Q_ASSERT(index < INT_MAX);
BindInfo info;
info.m_index = index;
++index;
info.m_function = function;
info.m_action = action;
info.m_receiver = receiver;
m_boundActions.push_back(info);
return info.m_index;
}
void CInputManager::processCombination(const CHotkeyCombination &combination)
{
if (m_captureActive)
{
if (combination.size() < m_capturedCombination.size())
{
emit combinationSelectionFinished(m_capturedCombination);
m_captureActive = false;
}
else
{
emit combinationSelectionChanged(combination);
m_capturedCombination = combination;
}
}
QString previousAction = m_configuredActions.value(m_lastCombination);
QString action = m_configuredActions.value(combination);
m_lastCombination = combination;
callFunctionsBy(previousAction, false);
callFunctionsBy(action, true);
}
}