From 199a1e5fcb42b364c6cff2784ee21e8afdb636ec Mon Sep 17 00:00:00 2001 From: Roland Winklmeier Date: Fri, 14 Aug 2015 20:21:27 +0200 Subject: [PATCH] refs #453 Refactor CInputManger and low level input handlers --- src/blackcore/context_application_proxy.cpp | 5 - src/blackcore/context_audio_impl.cpp | 6 +- src/blackcore/context_audio_impl.h | 3 - src/blackcore/input_manager.cpp | 169 +++++++++----- src/blackcore/input_manager.h | 124 +++++----- src/blackcore/settings/application.h | 46 ++++ src/blackinput/joystick.cpp | 16 +- src/blackinput/joystick.h | 40 +--- src/blackinput/keyboard.cpp | 22 +- src/blackinput/keyboard.h | 58 +---- src/blackinput/linux/joystick_linux.cpp | 27 ++- src/blackinput/linux/joystick_linux.h | 11 +- src/blackinput/linux/keyboard_linux.cpp | 189 +++++++++------ src/blackinput/linux/keyboard_linux.h | 44 +--- src/blackinput/linux/keymapping_linux.cpp | 100 -------- src/blackinput/linux/keymapping_linux.h | 48 ---- src/blackinput/osx/joystick_mac.cpp | 12 +- src/blackinput/osx/joystick_mac.h | 15 +- src/blackinput/osx/keyboard_mac.h | 26 +-- src/blackinput/osx/keyboard_mac.mm | 247 +++++++++++--------- src/blackinput/osx/keymapping_mac.h | 33 --- src/blackinput/osx/keymapping_mac.mm | 62 ----- src/blackinput/win/joystick_windows.cpp | 43 +--- src/blackinput/win/joystick_windows.h | 11 +- src/blackinput/win/keyboard_windows.cpp | 143 +++++------- src/blackinput/win/keyboard_windows.h | 26 +-- src/blackinput/win/keymapping_windows.cpp | 93 -------- src/blackinput/win/keymapping_windows.h | 46 ---- src/swiftgui_standard/swiftguistd.cpp | 22 +- src/swiftgui_standard/swiftguistd.h | 5 - src/swiftgui_standard/swiftguistd_init.cpp | 3 - 31 files changed, 609 insertions(+), 1086 deletions(-) create mode 100644 src/blackcore/settings/application.h delete mode 100644 src/blackinput/linux/keymapping_linux.cpp delete mode 100644 src/blackinput/linux/keymapping_linux.h delete mode 100644 src/blackinput/osx/keymapping_mac.h delete mode 100644 src/blackinput/osx/keymapping_mac.mm delete mode 100644 src/blackinput/win/keymapping_windows.cpp delete mode 100644 src/blackinput/win/keymapping_windows.h diff --git a/src/blackcore/context_application_proxy.cpp b/src/blackcore/context_application_proxy.cpp index e8113e888..b03837e8e 100644 --- a/src/blackcore/context_application_proxy.cpp +++ b/src/blackcore/context_application_proxy.cpp @@ -28,11 +28,6 @@ namespace BlackCore // this->m_dBusInterface = new CGenericDBusInterface(serviceName, IContextApplication::ObjectPath(), IContextApplication::InterfaceName(), connection, this); this->relaySignals(serviceName, connection); - // Enable event forwarding from GUI process to core - CInputManager *inputManager = CInputManager::getInstance(); - connect(inputManager, &CInputManager::hotkeyFuncEvent, this, &CContextApplicationProxy::processHotkeyFuncEvent); - inputManager->setEventForwarding(true); - connect(this, &IContextApplication::messageLogged, this, [](const CStatusMessage & message, const CIdentifier & origin) { if (!origin.isFromSameProcess()) diff --git a/src/blackcore/context_audio_impl.cpp b/src/blackcore/context_audio_impl.cpp index 28ac44427..aa678ccbf 100644 --- a/src/blackcore/context_audio_impl.cpp +++ b/src/blackcore/context_audio_impl.cpp @@ -26,7 +26,7 @@ using namespace BlackMisc; using namespace BlackMisc::Aviation; using namespace BlackMisc::Audio; -using namespace BlackMisc::Hardware; +using namespace BlackMisc::Input; using namespace BlackSound; namespace BlackCore @@ -42,10 +42,6 @@ namespace BlackCore // own aircraft may or may not be available const CCallsign ownCallsign = (this->getIContextOwnAircraft()) ? getIContextOwnAircraft()->getOwnAircraft().getCallsign() : CCallsign(); - // Register PTT hotkey function - m_inputManager = CInputManager::getInstance(); - m_handlePtt = m_inputManager->registerHotkeyFunc(CHotkeyFunction::Ptt(), this, &CContextAudio::ps_setVoiceTransmission); - m_channel1 = m_voice->createVoiceChannel(); m_channel1->setOwnAircraftCallsign(ownCallsign); connect(m_channel1.data(), &IVoiceChannel::connectionStatusChanged, this, &CContextAudio::ps_connectionStatusChanged); diff --git a/src/blackcore/context_audio_impl.h b/src/blackcore/context_audio_impl.h index a066d237e..e825b3da7 100644 --- a/src/blackcore/context_audio_impl.h +++ b/src/blackcore/context_audio_impl.h @@ -21,7 +21,6 @@ #include "voice_channel.h" #include "audio_device.h" #include "audio_mixer.h" -#include "input_manager.h" #include "blackinput/keyboard.h" #include "blackmisc/audio/voiceroomlist.h" @@ -154,8 +153,6 @@ namespace BlackCore QSharedPointer getVoiceChannelBy(const BlackMisc::Audio::CVoiceRoom &voiceRoom); - CInputManager *m_inputManager = nullptr; - CInputManager::RegistrationHandle m_handlePtt; std::unique_ptr m_voice; //!< underlying voice lib std::unique_ptr m_audioMixer; diff --git a/src/blackcore/input_manager.cpp b/src/blackcore/input_manager.cpp index 8fd4b8a3d..3184b647b 100644 --- a/src/blackcore/input_manager.cpp +++ b/src/blackcore/input_manager.cpp @@ -4,107 +4,152 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "input_manager.h" +#include "blackmisc/input/keyboardkeylist.h" using namespace BlackInput; using namespace BlackMisc; -using namespace BlackMisc::Hardware; +using namespace BlackMisc::Input; namespace BlackCore { - CInputManager *CInputManager::m_instance = nullptr; CInputManager::CInputManager(QObject *parent) : QObject(parent), - m_keyboard(IKeyboard::getInstance()), - m_joystick(IJoystick::getInstance()) + m_keyboard(std::move(IKeyboard::create(this))), + m_joystick(std::move(IJoystick::create(this))) { - connect(m_keyboard, &IKeyboard::keyUp, this, &CInputManager::ps_processKeyboardKeyUp); - connect(m_keyboard, &IKeyboard::keyDown, this, &CInputManager::ps_processKeyboardKeyDown); - connect(m_joystick, &IJoystick::buttonUp, this, &CInputManager::ps_processJoystickButtonUp); - connect(m_joystick, &IJoystick::buttonDown, this, &CInputManager::ps_processJoystickButtonDown); + connect(m_keyboard.get(), &IKeyboard::keyCombinationChanged, this, &CInputManager::ps_processKeyCombinationChanged); + connect(m_joystick.get(), &IJoystick::buttonCombinationChanged, this, &CInputManager::ps_processButtonCombinationChanged); } - CInputManager *CInputManager::getInstance() + CInputManager *CInputManager::instance() { - if (!m_instance) + static CInputManager instance; + return &instance; + } + + void CInputManager::registerAction(const QString &action) + { + if (!m_availableActions.contains(action)) { - m_instance = new CInputManager(); + m_availableActions.push_back(action); + emit hotkeyActionRegistered( { action } ); } - return m_instance; } - void CInputManager::changeHotkeySettings(Settings::CSettingKeyboardHotkeyList hotkeys) + void CInputManager::registerRemoteActions(const QStringList &actions) { - CKeyboardKeyList keyList; - for (Settings::CSettingKeyboardHotkey settingHotkey : hotkeys) + for (const auto &action : actions) { - CKeyboardKey key = settingHotkey.getKey(); - if (key.isEmpty()) continue; - - m_hashKeyboardKeyFunctions.insert(key, settingHotkey.getFunction()); - keyList.push_back(key); + if (!m_availableActions.contains(action)) + { + m_availableActions.push_back(action); + emit hotkeyActionRegistered( { action } ); + } } - m_keyboard->setKeysToMonitor(keyList); } - void CInputManager::ps_processKeyboardKeyDown(const CKeyboardKey &key) + void CInputManager::unbind(int index) { - if (!m_hashKeyboardKeyFunctions.contains(key)) return; - - // Get configured hotkey function - CHotkeyFunction hotkeyFunc = m_hashKeyboardKeyFunctions.value(key); - callFunctionsBy(hotkeyFunc, true); + 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::ps_processKeyboardKeyUp(const CKeyboardKey &key) + void CInputManager::ps_changeHotkeySettings() { - if (!m_hashKeyboardKeyFunctions.contains(key)) return; + m_configuredActions.clear(); + for (CActionHotkey actionHotkey : m_actionHotkeys.get()) + { + CHotkeyCombination combination = actionHotkey.getCombination(); + if (combination.isEmpty()) continue; - // Get configured hotkey function - CHotkeyFunction hotkeyFunc = m_hashKeyboardKeyFunctions.value(key); - callFunctionsBy(hotkeyFunc, false); + m_configuredActions.insert(combination, actionHotkey.getAction()); + } } - void CInputManager::ps_processJoystickButtonDown(const CJoystickButton &button) + void CInputManager::ps_processKeyCombinationChanged(const CHotkeyCombination &combination) { - qDebug() << "Pressed Button" << button.getButtonIndex(); - if (!m_hashJoystickKeyFunctions.contains(button)) return; - - // Get configured hotkey function - CHotkeyFunction hotkeyFunc = m_hashJoystickKeyFunctions.value(button); - callFunctionsBy(hotkeyFunc, true); + // Merge in the joystick part + CHotkeyCombination copy(combination); + copy.setJoystickButtons(m_lastCombination.getJoystickButtons()); + processCombination(copy); } - void CInputManager::ps_processJoystickButtonUp(const CJoystickButton &button) + void CInputManager::ps_processButtonCombinationChanged(const CHotkeyCombination &combination) { - qDebug() << "Released Button" << button.getButtonIndex(); - if (!m_hashJoystickKeyFunctions.contains(button)) return; - - // Get configured hotkey function - CHotkeyFunction hotkeyFunc = m_hashJoystickKeyFunctions.value(button); - callFunctionsBy(hotkeyFunc, false); + // Merge in the keyboard keys + CHotkeyCombination copy(combination); + copy.setKeyboardKeys(m_lastCombination.getKeyboardKeys()); + processCombination(copy); } - void CInputManager::callFunctionsBy(const CHotkeyFunction &hotkeyFunction, bool isKeyDown) + void CInputManager::startCapture() { - BlackMisc::Event::CEventHotkeyFunction hotkeyEvent(hotkeyFunction, isKeyDown); - if(m_eventForwardingEnabled) emit hotkeyFuncEvent(hotkeyEvent); - - if (!m_hashRegisteredFunctions.contains(hotkeyFunction)) return; - auto func = m_hashRegisteredFunctions.value(hotkeyFunction); - func(isKeyDown); + m_captureActive = true; + m_capturedCombination = {}; } - CInputManager::RegistrationHandle CInputManager::registerHotkeyFuncImpl(const BlackMisc::CHotkeyFunction &hotkeyFunction, - QObject *receiver, - std::function function) + void CInputManager::callFunctionsBy(const QString &action, bool isKeyDown) { - m_hashRegisteredFunctions.insert(hotkeyFunction, function); + if (action.isEmpty()) { return; } + if(m_actionRelayingEnabled) emit remoteActionFromLocal(action, isKeyDown); - RegistrationHandle handle; - handle.function = function; - handle.hotkeyFunction = hotkeyFunction; - handle.m_receiver = receiver; - return handle; + for (const auto &boundAction : 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; + } + + int CInputManager::bindImpl(const QString &action, QObject *receiver, std::function 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); } } diff --git a/src/blackcore/input_manager.h b/src/blackcore/input_manager.h index 80b5f6876..5bd1047a6 100644 --- a/src/blackcore/input_manager.h +++ b/src/blackcore/input_manager.h @@ -7,15 +7,13 @@ #define BLACKCORE_INPUTMANAGER_H #include "blackcoreexport.h" +#include "blackcore/settings/application.h" #include "blackinput/keyboard.h" #include "blackinput/joystick.h" -#include "blackmisc/hardware/keyboardkeylist.h" -#include "blackmisc/hardware/joystickbutton.h" -#include "blackmisc/hotkeyfunction.h" -#include "blackmisc/setkeyboardhotkeylist.h" -#include "blackmisc/eveventhotkeyfunction.h" +#include "blackmisc/input/hotkeycombination.h" #include #include +#include #include #include @@ -29,62 +27,67 @@ namespace BlackCore Q_OBJECT public: + //! Register new action + void registerAction(const QString &action); - //! \brief Handle to a registered hotkey function - struct RegistrationHandle - { - //! \brief Constructor - RegistrationHandle() {} - - BlackMisc::CHotkeyFunction hotkeyFunction; //!< Registered hotkey function - QPointer m_receiver; //!< Registered receiver - std::function function; //!< Registered function - }; + //! Register remote actions + void registerRemoteActions(const QStringList &actions); //! Register a new hotkey function - RegistrationHandle registerHotkeyFunc(const BlackMisc::CHotkeyFunction &hotkeyFunction, QObject *receiver, const QByteArray &slotName) - { - auto function = [=](bool isKeyDown){ QMetaObject::invokeMethod(receiver, slotName, Q_ARG(bool, isKeyDown)); }; - return registerHotkeyFuncImpl(hotkeyFunction, receiver, function); - } - - //! Register a new hotkey function - template - RegistrationHandle registerHotkeyFunc(const BlackMisc::CHotkeyFunction &hotkeyFunction, RecvObj *receiver, void (RecvObj:: *slotPointer)(bool)) + template + int bind(const QString &action, RecvObj *receiver, void (RecvObj:: *slotPointer)(bool)) { using namespace std::placeholders; auto function = std::bind(slotPointer, receiver, _1); - return registerHotkeyFuncImpl(hotkeyFunction, receiver, function); + return bindImpl(action, receiver, function); } //! Register a new hotkey function - template - RegistrationHandle registerHotkeyFunc(const BlackMisc::CHotkeyFunction &hotkeyFunction, QObject *receiver, Func functionObject) + template + int bind(const QString &action, QObject *receiver, Func functionObject) { - return registerHotkeyFuncImpl(hotkeyFunction, receiver, functionObject); + return bindImpl(action, receiver, functionObject); } + //! Unbind a slot + void unbind(int index); + + //! + //! Select a key combination as hotkey. This method returns immediatly. + //! Listen for signals combinationSelectionChanged and combinationSelectionFinished + //! to retrieve the user input. + void startCapture(); + //! Deletes all registered hotkeys. Be careful with this method! - void resetAllHotkeyFuncs() { m_hashRegisteredFunctions.clear(); } + void resetAllActions() { m_configuredActions.clear(); } + + //! Get all available and known actions + QStringList allAvailableActions() const { return m_availableActions; } //! Enable event forwarding to core - void setEventForwarding(bool enabled) { m_eventForwardingEnabled = enabled; } - - //! Creates a native keyboard handler object - static CInputManager *getInstance(); - - public slots: - - //! Change hotkey settings - void changeHotkeySettings(BlackMisc::Settings::CSettingKeyboardHotkeyList hotkeys); + void setForwarding(bool enabled) { m_actionRelayingEnabled = enabled; } //! Call functions by hotkeyfunction - void callFunctionsBy(const BlackMisc::CHotkeyFunction &hotkeyFunction, bool isKeyDown); + void callFunctionsBy(const QString &action, bool isKeyDown); + + //! Triggers a key event manually and calls the registered functions. + void triggerKey(const BlackMisc::Input::CHotkeyCombination &combination, bool isPressed); + + //! Creates a native keyboard handler object + static CInputManager *instance(); signals: - //! Event hotkeyfunction occured - void hotkeyFuncEvent(const BlackMisc::Event::CEventHotkeyFunction &event); + void remoteActionFromLocal(const QString &action, bool argument); + + //! Selected combination has changed + void combinationSelectionChanged(const BlackMisc::Input::CHotkeyCombination &combination); + + //! Combination selection has finished + void combinationSelectionFinished(const BlackMisc::Input::CHotkeyCombination &combination); + + //! New hotkey action is registered + void hotkeyActionRegistered(const QStringList &actions); protected: //! Constructor @@ -92,28 +95,43 @@ namespace BlackCore private slots: - void ps_processKeyboardKeyDown(const BlackMisc::Hardware::CKeyboardKey &); + void ps_processKeyCombinationChanged(const BlackMisc::Input::CHotkeyCombination &combination); - void ps_processKeyboardKeyUp(const BlackMisc::Hardware::CKeyboardKey &); + void ps_processButtonCombinationChanged(const BlackMisc::Input::CHotkeyCombination &combination); - void ps_processJoystickButtonDown(const BlackMisc::Hardware::CJoystickButton &button); - - void ps_processJoystickButtonUp(const BlackMisc::Hardware::CJoystickButton &button); + //! Change hotkey settings + void ps_changeHotkeySettings(); private: + //! Handle to a bound action + struct BindInfo + { + // Using unique int intex for identification because std::function does not have a operator== + int m_index = 0; + QString m_action; + QPointer m_receiver; + std::function m_function; + }; - RegistrationHandle registerHotkeyFuncImpl(const BlackMisc::CHotkeyFunction &hotkeyFunction, QObject *receiver, std::function function); + int bindImpl(const QString &action, QObject *receiver, std::function function); + + void processCombination(const BlackMisc::Input::CHotkeyCombination &combination); static CInputManager *m_instance; - BlackInput::IKeyboard *m_keyboard = nullptr; - BlackInput::IJoystick *m_joystick = nullptr; + std::unique_ptr m_keyboard; + std::unique_ptr m_joystick; - QHash > m_hashRegisteredFunctions; - QHash m_hashKeyboardKeyFunctions; - QHash m_hashJoystickKeyFunctions; + QStringList m_availableActions; + QHash m_configuredActions; + QVector m_boundActions; - bool m_eventForwardingEnabled = false; + bool m_actionRelayingEnabled = false; + bool m_captureActive = false; + BlackMisc::Input::CHotkeyCombination m_lastCombination; + BlackMisc::Input::CHotkeyCombination m_capturedCombination; + + BlackCore::CSetting m_actionHotkeys { this, &CInputManager::ps_changeHotkeySettings }; }; } diff --git a/src/blackcore/settings/application.h b/src/blackcore/settings/application.h new file mode 100644 index 000000000..deb855b70 --- /dev/null +++ b/src/blackcore/settings/application.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2015 + * 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. + */ + +//! \file + +#ifndef BLACKCORE_SETTINGS_APPLICATION_H +#define BLACKCORE_SETTINGS_APPLICATION_H + +#include "blackcore/settingscache.h" +#include "blackmisc/input/actionhotkeylist.h" + +namespace BlackCore +{ + namespace Settings + { + namespace Application + { + //! User configured hotkeys + struct ActionHotkeys : public CSettingTrait + { + //! \copydoc BlackCore::CSetting::key + static const char *key() { return "application/actionhotkeys"; } + + //! \copydoc BlackCore::CSetting::isValid + static bool isValid(const BlackMisc::Input::CActionHotkeyList &value) + { + for (const auto &actionHotkey : value) + { + if (actionHotkey.getApplicableMachine().getMachineName().isEmpty() || + actionHotkey.getAction().isEmpty() || + actionHotkey.getCombination().isEmpty()) { return false; } + } + return true; + } + }; + } + } +} + +#endif diff --git a/src/blackinput/joystick.cpp b/src/blackinput/joystick.cpp index 403c911c7..07609de63 100644 --- a/src/blackinput/joystick.cpp +++ b/src/blackinput/joystick.cpp @@ -21,27 +21,23 @@ namespace BlackInput { - IJoystick *IJoystick::m_instance = nullptr; IJoystick::IJoystick(QObject *parent) : QObject(parent) { } - IJoystick *IJoystick::getInstance() + std::unique_ptr IJoystick::create(QObject *parent) { - if (!m_instance) - { #if defined(Q_OS_WIN) - m_instance = new CJoystickWindows; + std::unique_ptr ptr(new CJoystickWindows(parent)); #elif defined(Q_OS_LINUX) - m_instance = new CJoystickLinux; + std::unique_ptr ptr(new CJoystickLinux(parent)); #elif defined(Q_OS_OSX) - m_instance = new CJoystickMac; + std::unique_ptr ptr(new CJoystickMac(parent)); #endif - Q_ASSERT_X(m_instance, "IJoystick::getInstance", "Pointer to IJoystick is nullptr!"); - } - return m_instance; + + return ptr; } } // BlackInput diff --git a/src/blackinput/joystick.h b/src/blackinput/joystick.h index 9ce0a0dcb..d2949e058 100644 --- a/src/blackinput/joystick.h +++ b/src/blackinput/joystick.h @@ -13,60 +13,32 @@ #define BLACKINPUT_JOYSTICK_H #include "blackinputexport.h" -#include "blackmisc/hardware/joystickbutton.h" -#include +#include "blackmisc/input/hotkeycombination.h" #include -#include -#include +#include namespace BlackInput { /*! - * \brief Abstract interface for native joystick handling. - * \todo Add implementation for Linux and OSX. + * Abstract interface for native joystick handling. */ class BLACKINPUT_EXPORT IJoystick : public QObject { Q_OBJECT public: - - //! Operation mode - enum Mode - { - ModeNominal, - ModeCapture - }; - //! Constructor IJoystick(QObject *parent = nullptr); //! Destructor virtual ~IJoystick() {} - //! Start joystick button selection for settings configuration - virtual void startCapture() = 0; - - //! Simulating press/release of a joystick button - virtual void triggerButton(const BlackMisc::Hardware::CJoystickButton button, bool isPressed) = 0; - //! Creates a native joystick handler object - static IJoystick *getInstance(); + static std::unique_ptr create(QObject *parent = nullptr); signals: - - //! User has selected a joystick button - void buttonSelectionFinished(const BlackMisc::Hardware::CJoystickButton &button); - - //! Button down - void buttonDown(const BlackMisc::Hardware::CJoystickButton &); - - //! Button up - void buttonUp(const BlackMisc::Hardware::CJoystickButton &); - - private: - - static IJoystick *m_instance; + //! Joystick button combination has changed + void buttonCombinationChanged(const BlackMisc::Input::CHotkeyCombination &); }; } diff --git a/src/blackinput/keyboard.cpp b/src/blackinput/keyboard.cpp index 929fafa82..54c49c1dd 100644 --- a/src/blackinput/keyboard.cpp +++ b/src/blackinput/keyboard.cpp @@ -17,28 +17,20 @@ namespace BlackInput { - IKeyboard *IKeyboard::m_instance = nullptr; - IKeyboard::IKeyboard(QObject *parent) : - QObject(parent) - { - } + IKeyboard::IKeyboard(QObject *parent) : QObject(parent) {} - IKeyboard *IKeyboard::getInstance() + std::unique_ptr IKeyboard::create(QObject *parent) { - if (!m_instance) - { #if defined(Q_OS_WIN) - m_instance = new CKeyboardWindows; + std::unique_ptr ptr(new CKeyboardWindows(parent)); #elif defined(Q_OS_LINUX) - m_instance = new CKeyboardLinux; + std::unique_ptr ptr(new CKeyboardLinux(parent)); #elif defined(Q_OS_OSX) - m_instance = new CKeyboardMac; + std::unique_ptr ptr(new CKeyboardMac(parent)); #endif - Q_ASSERT_X(m_instance, "IKeyboard::getInstance", "Pointer to IKeyboard is NULL!"); - m_instance->init(); - } - return m_instance; + ptr->init(); + return ptr; } } // BlackInput diff --git a/src/blackinput/keyboard.h b/src/blackinput/keyboard.h index ff3204a99..2707a3441 100644 --- a/src/blackinput/keyboard.h +++ b/src/blackinput/keyboard.h @@ -11,11 +11,10 @@ #define BLACKINPUT_KEYBOARD_H #include "blackinputexport.h" -#include "blackmisc/hardware/keyboardkeylist.h" -#include +#include "blackmisc/input/keyboardkeylist.h" +#include "blackmisc/input/hotkeycombination.h" #include -#include -#include +#include namespace BlackInput { @@ -27,62 +26,18 @@ namespace BlackInput { Q_OBJECT public: - - //! Operation mode - enum Mode - { - Mode_Nominal, - Mode_Capture - }; - //! Constructor IKeyboard(QObject *parent = nullptr); //! Destructor virtual ~IKeyboard() {} - //! Set the list of keys to monitor - virtual void setKeysToMonitor(const BlackMisc::Hardware::CKeyboardKeyList &keylist) = 0; - - /*! - * Select a key combination as hotkey. This method returns immediatly. - * Listen for signals keySelectionChanged and keySelectionFinished - * to retrieve the user input. - * \param ignoreNextKey - * Set to true, if you want to ignore the first key, - * e.g. [ENTER] in case you are running from command line. - */ - virtual void startCapture(bool ignoreNextKey) = 0; - - /*! - * Triggers a key event manually and calls the registered functions. - * \param key - * \param isPressed - */ - virtual void triggerKey(const BlackMisc::Hardware::CKeyboardKey &key, bool isPressed) = 0; - //! Creates a native keyboard handler object - static IKeyboard *getInstance(); + static std::unique_ptr create(QObject *parent = nullptr); signals: - - /*! - * Key selection has changed, but is not finished yet. - * \param key - */ - void keySelectionChanged(BlackMisc::Hardware::CKeyboardKey key); - - /*! - * Key selection has finished. - * \param key - */ - void keySelectionFinished(BlackMisc::Hardware::CKeyboardKey key); - - //! Key down - void keyDown(const BlackMisc::Hardware::CKeyboardKey &); - - //! Key up - void keyUp(const BlackMisc::Hardware::CKeyboardKey &); + //! Key combination changed + void keyCombinationChanged(const BlackMisc::Input::CHotkeyCombination &); protected: @@ -92,7 +47,6 @@ namespace BlackInput virtual bool init() = 0; private: - static IKeyboard *m_instance; }; } diff --git a/src/blackinput/linux/joystick_linux.cpp b/src/blackinput/linux/joystick_linux.cpp index 3135ff7cb..13e35a5d7 100644 --- a/src/blackinput/linux/joystick_linux.cpp +++ b/src/blackinput/linux/joystick_linux.cpp @@ -18,7 +18,7 @@ #include using namespace BlackMisc; -using namespace BlackMisc::Hardware; +using namespace BlackMisc::Input; namespace { @@ -42,17 +42,6 @@ namespace BlackInput ps_directoryChanged(inputDevicesDir()); } - void CJoystickLinux::startCapture() - { - - } - - void CJoystickLinux::triggerButton(const CJoystickButton button, bool isPressed) - { - if (!isPressed) emit buttonUp(button); - else emit buttonDown(button); - } - void CJoystickLinux::cleanupJoysticks() { for (auto it = m_joysticks.begin(); it != m_joysticks.end();) @@ -123,17 +112,27 @@ namespace BlackInput QFile *joystick = qobject_cast(object); Q_ASSERT(joystick); + struct js_event event; while (joystick->read(reinterpret_cast(&event), sizeof(event)) == sizeof(event)) { + BlackMisc::Input::CHotkeyCombination oldCombination(m_buttonCombination); switch (event.type & ~JS_EVENT_INIT) { case JS_EVENT_BUTTON: if (event.value) - emit buttonDown(CJoystickButton(event.number)); + { + m_buttonCombination.addJoystickButton(event.number); + } else - emit buttonUp(CJoystickButton(event.number)); + { + m_buttonCombination.removeJoystickButton(event.number); + } + if (oldCombination != m_buttonCombination) + { + emit buttonCombinationChanged(m_buttonCombination); + } break; } } diff --git a/src/blackinput/linux/joystick_linux.h b/src/blackinput/linux/joystick_linux.h index 1dc05f3fb..1b8effad4 100644 --- a/src/blackinput/linux/joystick_linux.h +++ b/src/blackinput/linux/joystick_linux.h @@ -13,7 +13,7 @@ //! \file #include "blackinput/joystick.h" -#include "blackmisc/hardware/joystickbutton.h" +#include "blackmisc/input/joystickbutton.h" #include "blackmisc/collection.h" #include #include @@ -41,12 +41,6 @@ namespace BlackInput //! \brief Destructor virtual ~CJoystickLinux() = default; - //! \copydoc IJoystick::startCapture() - virtual void startCapture() override; - - //! \copydoc IJoystick::triggerButton() - virtual void triggerButton(const BlackMisc::Hardware::CJoystickButton button, bool isPressed) override; - private: friend class IJoystick; @@ -71,8 +65,7 @@ namespace BlackInput void ps_readInput(QObject *object); private: - - IJoystick::Mode m_mode = ModeNominal; //!< Current working mode + BlackMisc::Input::CHotkeyCombination m_buttonCombination; QSignalMapper *m_mapper = nullptr; //!< Maps device handles QMap m_joysticks; //!< All read joysticks, file path <-> file instance pairs QFileSystemWatcher *m_inputWatcher = nullptr; diff --git a/src/blackinput/linux/keyboard_linux.cpp b/src/blackinput/linux/keyboard_linux.cpp index bb5766cf2..6f5b06fff 100644 --- a/src/blackinput/linux/keyboard_linux.cpp +++ b/src/blackinput/linux/keyboard_linux.cpp @@ -4,29 +4,79 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "keyboard_linux.h" -#include "keymapping_linux.h" #include "blackmisc/logmessage.h" #include #include #include #include +#include #include #include #include +#include +#include -using namespace BlackMisc::Hardware; +using namespace BlackMisc; +using namespace BlackMisc::Input; namespace BlackInput { - CKeyboardLinux::CKeyboardLinux(QObject *parent) : - IKeyboard(parent), - m_ignoreNextKey(false), - m_mode(Mode_Nominal) + + static QHash keyMapping { + { XK_0, Key_0 }, + { XK_1, Key_1 }, + { XK_2, Key_2 }, + { XK_3, Key_3 }, + { XK_4, Key_4 }, + { XK_5, Key_5 }, + { XK_6, Key_6 }, + { XK_7, Key_7 }, + { XK_8, Key_8 }, + { XK_9, Key_9 }, + { XK_a, Key_A }, + { XK_b, Key_B }, + { XK_c, Key_C }, + { XK_d, Key_D }, + { XK_e, Key_E }, + { XK_f, Key_F }, + { XK_g, Key_G }, + { XK_h, Key_H }, + { XK_i, Key_I }, + { XK_j, Key_J }, + { XK_k, Key_K }, + { XK_l, Key_L }, + { XK_m, Key_M }, + { XK_n, Key_N }, + { XK_o, Key_O }, + { XK_p, Key_P }, + { XK_q, Key_Q }, + { XK_r, Key_R }, + { XK_s, Key_S }, + { XK_t, Key_T }, + { XK_u, Key_U }, + { XK_v, Key_V }, + { XK_w, Key_W }, + { XK_x, Key_X }, + { XK_y, Key_Y }, + { XK_z, Key_Z }, + { XK_Shift_L, Key_ShiftLeft }, + { XK_Shift_R, Key_ShiftRight }, + { XK_Control_L, Key_ControlLeft }, + { XK_Control_R, Key_ControlRight }, + { XK_Alt_L, Key_AltLeft }, + { XK_Alt_R, Key_AltRight }, + }; + + CKeyboardLinux::CKeyboardLinux(QObject *parent) : + IKeyboard(parent) + { + m_display = XOpenDisplay(nullptr); } CKeyboardLinux::~CKeyboardLinux() { + if (m_display) XCloseDisplay(m_display); } bool CKeyboardLinux::init() @@ -39,24 +89,6 @@ namespace BlackInput return true; } - void CKeyboardLinux::setKeysToMonitor(const CKeyboardKeyList &keylist) - { - m_listMonitoredKeys = keylist; - } - - void CKeyboardLinux::startCapture(bool ignoreNextKey) - { - m_mode = Mode_Capture; - m_ignoreNextKey = ignoreNextKey; - m_pressedKey.setKeyObject(CKeyboardKey()); - } - - void CKeyboardLinux::triggerKey(const CKeyboardKey &key, bool isPressed) - { - if (!isPressed) emit keyUp(key); - else emit keyDown(key); - } - void CKeyboardLinux::deviceDirectoryChanged(const QString &dir) { QDir eventFiles(dir, QLatin1String("event*"), 0, QDir::System); @@ -96,7 +128,9 @@ namespace BlackInput default: continue; } - int keyCode = eventInput.code; + + // The + 8 offset is required for XkbKeycodeToKeysym to output the correct Keysym + int keyCode = eventInput.code + 8; keyEvent(keyCode, isPressed); } @@ -112,14 +146,6 @@ namespace BlackInput } } - void CKeyboardLinux::sendCaptureNotification(const CKeyboardKey &key, bool isFinished) - { - if (isFinished) - emit keySelectionFinished(key); - else - emit keySelectionChanged(key); - } - void CKeyboardLinux::addRawInputDevice(const QString &filePath) { QSharedPointer inputFile(new QFile(filePath)); @@ -170,62 +196,73 @@ namespace BlackInput } } - void CKeyboardLinux::keyEvent(int virtualKeyCode, bool isPressed) + void CKeyboardLinux::keyEvent(int keyCode, bool isPressed) { - if (CKeyMappingLinux::isMouseButton(virtualKeyCode)) - return; + if (isMouseButton(keyCode)) { return; } - BlackMisc::Hardware::CKeyboardKey lastPressedKey = m_pressedKey; - if (m_ignoreNextKey) - { - m_ignoreNextKey = false; - return; - } - - bool isFinished = false; + BlackMisc::Input::CHotkeyCombination oldCombination(m_keyCombination); if (isPressed) { - if (CKeyMappingLinux::isModifier(virtualKeyCode)) - m_pressedKey.addModifier(CKeyMappingLinux::convertToModifier(virtualKeyCode)); - else - { - m_pressedKey.setKey(CKeyMappingLinux::convertToKey(virtualKeyCode)); - } + auto key = convertToKey(keyCode); + if (key == Key_Unknown) { return; } + + m_keyCombination.addKeyboardKey(key); } else { - if (CKeyMappingLinux::isModifier(virtualKeyCode)) - m_pressedKey.removeModifier(CKeyMappingLinux::convertToModifier(virtualKeyCode)); - else - { - m_pressedKey.setKey(Qt::Key_unknown); - } + auto key = convertToKey(keyCode); + if (key == Key_Unknown) { return; } - isFinished = true; + m_keyCombination.removeKeyboardKey(key); } - if (lastPressedKey == m_pressedKey) - return; - -#ifdef DEBUG_KEYBOARD - qDebug() << "Virtual key: " << virtualKeyCode; -#endif - if (m_mode == Mode_Capture) + if (oldCombination != m_keyCombination) { - if (isFinished) - { - sendCaptureNotification(lastPressedKey, true); - m_mode = Mode_Nominal; - } - else - { - sendCaptureNotification(m_pressedKey, false); - } + emit keyCombinationChanged(m_keyCombination); } - else + } + + BlackMisc::Input::KeyCode CKeyboardLinux::convertToKey(int keyCode) + { + // The keycode received from kernel does not take keyboard layouts into account. + // It always defaults to US keyboards. In contrast to kernel devices, X11 is aware + // of user keyboard layouts. The magic below translates the key code + // into the correct symbol via a X11 connection. + // Summary of translations: + // Kernel key code -> X11 key symbol -> swift key code + + auto keySym = XkbKeycodeToKeysym(m_display, keyCode, 0, 0); + return keyMapping.value(keySym, Key_Unknown); + } + + bool CKeyboardLinux::isModifier(int keyCode) + { + auto keySym = XkbKeycodeToKeysym(m_display, keyCode, 0, 0); + switch (keySym) { - if (m_listMonitoredKeys.contains(lastPressedKey)) emit keyUp(lastPressedKey); - if (m_listMonitoredKeys.contains(m_pressedKey)) emit keyDown(m_pressedKey); + case XK_Shift_L: + case XK_Shift_R: + case XK_Control_L: + case XK_Control_R: + case XK_Alt_L: + case XK_Alt_R: + return true; + default: return false; + } + + return false; + } + + bool CKeyboardLinux::isMouseButton(int keyCode) + { + switch (keyCode) + { + case BTN_LEFT: + case BTN_RIGHT: + case BTN_MIDDLE: + return true; + default: + return false; } } } diff --git a/src/blackinput/linux/keyboard_linux.h b/src/blackinput/linux/keyboard_linux.h index 7515899e8..50469ffd8 100644 --- a/src/blackinput/linux/keyboard_linux.h +++ b/src/blackinput/linux/keyboard_linux.h @@ -11,16 +11,18 @@ #define BLACKINPUT_KEYBOARD_LINUX_H #include "blackinput/keyboard.h" -#include "blackmisc/hardware/keyboardkeylist.h" +#include "blackmisc/input/hotkeycombination.h" #include +#include +#include + class QFileSystemWatcher; class QFile; namespace BlackInput { //! \brief Linux implemenation of IKeyboard using hook procedure - //! \todo Change QHash to a CCollection object class CKeyboardLinux : public IKeyboard { Q_OBJECT @@ -36,15 +38,6 @@ namespace BlackInput //! \brief Destructor virtual ~CKeyboardLinux(); - //! Set the list of keys to monitor - virtual void setKeysToMonitor(const BlackMisc::Hardware::CKeyboardKeyList &keylist) override; - - //! \copydoc IKeyboard::selectKey() - virtual void startCapture(bool ignoreNextKey = false) override; - - //! \copydoc IKeyboard::triggerKey() - virtual void triggerKey(const BlackMisc::Hardware::CKeyboardKey &key, bool isPressed) override; - protected: //! \copydoc IKeyboard::init() @@ -65,33 +58,18 @@ namespace BlackInput //! \brief Constructor CKeyboardLinux(QObject *parent = nullptr); - /*! - * \brief Constructor - * \param keySet - * \param isFinished - */ - void sendCaptureNotification(const BlackMisc::Hardware::CKeyboardKey &key, bool isFinished); - - /*! - * \brief Add new raw input device - * \param filePath Path to device file - */ void addRawInputDevice(const QString &filePath); + void keyEvent(int keyCode, bool isPressed); + BlackMisc::Input::KeyCode convertToKey(int keyCode); + bool isModifier(int keyCode); + bool isMouseButton(int keyCode); - /*! - * \brief Process new key event - * \param virtualKeyCode - * \param isPressed - */ - void keyEvent(int virtualKeyCode, bool isPressed); - - BlackMisc::Hardware::CKeyboardKeyList m_listMonitoredKeys; //!< Registered keys - BlackMisc::Hardware::CKeyboardKey m_pressedKey; //!< Set of virtual keys pressed in the last cycle - bool m_ignoreNextKey; //!< Is true if the next key needs to be ignored - Mode m_mode; //!< Operation mode + BlackMisc::Input::CHotkeyCombination m_keyCombination; //!< Current status of pressed keys; QFileSystemWatcher *m_devInputWatcher; //!< Watches the device file system for input devices QHash> m_keyboardDevices; //!< All known input devices + + Display *m_display; }; } diff --git a/src/blackinput/linux/keymapping_linux.cpp b/src/blackinput/linux/keymapping_linux.cpp deleted file mode 100644 index b9a667717..000000000 --- a/src/blackinput/linux/keymapping_linux.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (C) 2013 VATSIM Community / contributors - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "keymapping_linux.h" -#include -#include - -using namespace BlackMisc::Hardware; - -namespace BlackInput -{ - Qt::Key CKeyMappingLinux::convertToKey(int virtualKey) - { - switch (virtualKey) - { - case KEY_0: return Qt::Key_0; break; - case KEY_1: return Qt::Key_1; break; - case KEY_2: return Qt::Key_2; break; - case KEY_3: return Qt::Key_3; break; - case KEY_4: return Qt::Key_4; break; - case KEY_5: return Qt::Key_5; break; - case KEY_6: return Qt::Key_6; break; - case KEY_7: return Qt::Key_7; break; - case KEY_8: return Qt::Key_8; break; - case KEY_9: return Qt::Key_9; break; - case KEY_A: return Qt::Key_A; break; - case KEY_B: return Qt::Key_B; break; - case KEY_C: return Qt::Key_C; break; - case KEY_D: return Qt::Key_D; break; - case KEY_E: return Qt::Key_E; break; - case KEY_F: return Qt::Key_F; break; - case KEY_G: return Qt::Key_G; break; - case KEY_H: return Qt::Key_H; break; - case KEY_I: return Qt::Key_I; break; - case KEY_J: return Qt::Key_J; break; - case KEY_K: return Qt::Key_K; break; - case KEY_L: return Qt::Key_L; break; - case KEY_M: return Qt::Key_M; break; - case KEY_N: return Qt::Key_N; break; - case KEY_O: return Qt::Key_O; break; - case KEY_P: return Qt::Key_P; break; - case KEY_Q: return Qt::Key_Q; break; - case KEY_R: return Qt::Key_R; break; - case KEY_S: return Qt::Key_S; break; - case KEY_T: return Qt::Key_T; break; - case KEY_U: return Qt::Key_U; break; - case KEY_V: return Qt::Key_V; break; - case KEY_W: return Qt::Key_W; break; - case KEY_X: return Qt::Key_X; break; - case KEY_Y: return Qt::Key_Y; break; - case KEY_Z: return Qt::Key_Z; break; - default: return Qt::Key_unknown; break; - } - } - - CKeyboardKey::Modifier CKeyMappingLinux::convertToModifier(int virtualKey) - { - switch (virtualKey) - { - case KEY_LEFTSHIFT: return CKeyboardKey::ModifierShiftLeft; break; - case KEY_RIGHTSHIFT: return CKeyboardKey::ModifierShiftRight; break; - case KEY_LEFTCTRL: return CKeyboardKey::ModifierCtrlLeft; break; - case KEY_RIGHTCTRL: return CKeyboardKey::ModifierCtrlRight; break; - case KEY_LEFTALT: return CKeyboardKey::ModifierAltLeft; break; - case KEY_RIGHTALT: return CKeyboardKey::ModifierAltRight; break; - default: return CKeyboardKey::ModifierNone; break; - } - } - - bool CKeyMappingLinux::isModifier(int virtualKey) - { - switch (virtualKey) - { - case KEY_LEFTSHIFT: - case KEY_RIGHTSHIFT: - case KEY_LEFTCTRL: - case KEY_RIGHTCTRL: - case KEY_LEFTALT: - case KEY_RIGHTALT: - return true; - default: return false; - } - } - - bool CKeyMappingLinux::isMouseButton(int virtualKey) - { - switch (virtualKey) - { - case BTN_LEFT: - case BTN_RIGHT: - case BTN_MIDDLE: - return true; - default: - return false; - } - } - -} // namespace BlackInput diff --git a/src/blackinput/linux/keymapping_linux.h b/src/blackinput/linux/keymapping_linux.h deleted file mode 100644 index 758c1a984..000000000 --- a/src/blackinput/linux/keymapping_linux.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (C) 2013 VATSIM Community / contributors - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - -#ifndef BLACKINPUT_KEYMAPPING_LINUX_H -#define BLACKINPUT_KEYMAPPING_LINUX_H - -#include "blackmisc/hardware/keyboardkey.h" - -namespace BlackInput -{ - //! \brief This class provides methods to map between windows virtual keys and CKeyboardKey - class CKeyMappingLinux - { - public: - /*! - * \brief Converts a set of windows virtual keys to a CKeySet object - * \param virtualKey - * \return - */ - static BlackMisc::Hardware::CKeyboardKey::Modifier convertToModifier(int virtualKey); - - /*! - * \brief Convert to Qt key - * \param virtualKey - * \return - */ - static Qt::Key convertToKey(int virtualKey); - - /*! - * \brief Checks if its a modifier key - * \param virtualKey - * \return - */ - static bool isModifier(int virtualKey); - - /*! - * \brief Checks if its a mouse button - * \param virtualKey - * \return - */ - static bool isMouseButton(int virtualKey); - }; - -} // namespace BlackInput -#endif // guard diff --git a/src/blackinput/osx/joystick_mac.cpp b/src/blackinput/osx/joystick_mac.cpp index 5226ccb4a..63d8618cc 100644 --- a/src/blackinput/osx/joystick_mac.cpp +++ b/src/blackinput/osx/joystick_mac.cpp @@ -9,7 +9,7 @@ #include "joystick_mac.h" -using namespace BlackMisc::Hardware; +using namespace BlackMisc::Input; namespace BlackInput { @@ -22,14 +22,4 @@ namespace BlackInput { } - void CJoystickMac::startCapture() - { - } - - void CJoystickMac::triggerButton(const CJoystickButton button, bool isPressed) - { - if(!isPressed) emit buttonUp(button); - else emit buttonDown(button); - } - } // namespace BlackInput diff --git a/src/blackinput/osx/joystick_mac.h b/src/blackinput/osx/joystick_mac.h index f0381c128..d6f9679f7 100644 --- a/src/blackinput/osx/joystick_mac.h +++ b/src/blackinput/osx/joystick_mac.h @@ -13,13 +13,13 @@ //! \file #include "blackinput/joystick.h" -#include "blackmisc/hardware/joystickbutton.h" +#include "blackmisc/input/joystickbutton.h" #include "blackmisc/collection.h" -#include namespace BlackInput { - //! Linux implemenation of IJoystick with DirectInput + //! OSX implemenation of IJoystick + //! \todo Not implmeneted yet class CJoystickMac : public IJoystick { Q_OBJECT @@ -35,20 +35,11 @@ namespace BlackInput //! \brief Destructor virtual ~CJoystickMac(); - //! \copydoc IJoystick::startCapture() - virtual void startCapture() override; - - //! \copydoc IJoystick::triggerButton() - virtual void triggerButton(const BlackMisc::Hardware::CJoystickButton button, bool isPressed) override; - private: - friend class IJoystick; //! Destructor CJoystickMac(QObject *parent = nullptr); - - IJoystick::Mode m_mode = ModeNominal; //!< Current working mode }; } // namespace BlackInput diff --git a/src/blackinput/osx/keyboard_mac.h b/src/blackinput/osx/keyboard_mac.h index 7f31c22ca..b40dff6fd 100644 --- a/src/blackinput/osx/keyboard_mac.h +++ b/src/blackinput/osx/keyboard_mac.h @@ -13,7 +13,7 @@ #define BLACKINPUT_KEYBOARD_MAC_H #include "blackinput/keyboard.h" -#include "blackmisc/hardware/keyboardkeylist.h" +#include "blackmisc/input/hotkeycombination.h" #include class __CGEvent; @@ -27,13 +27,11 @@ typedef __CGEventTapProxy* CGEventTapProxy; //!< Max event proxy definition namespace BlackInput { //! Mac OSX implemenation of IKeyboard using hook procedure - //! \todo Change QHash to a CCollection object class CKeyboardMac : public IKeyboard { Q_OBJECT public: - //! Copy Constructor CKeyboardMac(CKeyboardMac const&) = delete; @@ -43,15 +41,6 @@ namespace BlackInput //! Destructor virtual ~CKeyboardMac(); - //! Set the list of keys to monitor - virtual void setKeysToMonitor(const BlackMisc::Hardware::CKeyboardKeyList &keylist) override; - - //! \copydoc IKeyboard::selectKey() - virtual void startCapture(bool ignoreNextKey = false) override; - - //! \copydoc IKeyboard::triggerKey() - virtual void triggerKey(const BlackMisc::Hardware::CKeyboardKey &key, bool isPressed) override; - //! Process key event virtual void processKeyEvent(CGEventType type, CGEventRef event); @@ -66,23 +55,14 @@ namespace BlackInput //! Constructor CKeyboardMac(QObject *parent = nullptr); - - /*! - * Constructor - * \param keySet - * \param isFinished - */ - void sendCaptureNotification(const BlackMisc::Hardware::CKeyboardKey &key, bool isFinished); + BlackMisc::Input::KeyCode convertToKey(int keyCode); static CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon); - BlackMisc::Hardware::CKeyboardKeyList m_listMonitoredKeys; //!< Registered keys - BlackMisc::Hardware::CKeyboardKey m_pressedKey; //!< Set of virtual keys pressed in the last cycle - bool m_ignoreNextKey; //!< Is true if the next key needs to be ignored - Mode m_mode; //!< Operation mode + BlackMisc::Input::CHotkeyCombination m_keyCombination; //!< Current status of pressed keys; }; } diff --git a/src/blackinput/osx/keyboard_mac.mm b/src/blackinput/osx/keyboard_mac.mm index 8b876b74e..397165d2d 100644 --- a/src/blackinput/osx/keyboard_mac.mm +++ b/src/blackinput/osx/keyboard_mac.mm @@ -8,22 +8,62 @@ */ #include "keyboard_mac.h" -#include "keymapping_mac.h" -#include +#include #include #include #include #include #include #include +#include -using namespace BlackMisc::Hardware; +using namespace BlackMisc::Input; namespace BlackInput { + + static QHash keyMapping + { + { kVK_ANSI_0, Key_0 }, + { kVK_ANSI_1, Key_1 }, + { kVK_ANSI_2, Key_2 }, + { kVK_ANSI_3, Key_3 }, + { kVK_ANSI_4, Key_4 }, + { kVK_ANSI_5, Key_5 }, + { kVK_ANSI_6, Key_6 }, + { kVK_ANSI_7, Key_7 }, + { kVK_ANSI_8, Key_8 }, + { kVK_ANSI_9, Key_9 }, + { kVK_ANSI_A, Key_A }, + { kVK_ANSI_B, Key_B }, + { kVK_ANSI_C, Key_C }, + { kVK_ANSI_D, Key_D }, + { kVK_ANSI_E, Key_E }, + { kVK_ANSI_F, Key_F }, + { kVK_ANSI_G, Key_G }, + { kVK_ANSI_H, Key_H }, + { kVK_ANSI_I, Key_I }, + { kVK_ANSI_J, Key_J }, + { kVK_ANSI_K, Key_K }, + { kVK_ANSI_L, Key_L }, + { kVK_ANSI_M, Key_M }, + { kVK_ANSI_N, Key_N }, + { kVK_ANSI_O, Key_O }, + { kVK_ANSI_P, Key_P }, + { kVK_ANSI_Q, Key_Q }, + { kVK_ANSI_R, Key_R }, + { kVK_ANSI_S, Key_S }, + { kVK_ANSI_T, Key_T }, + { kVK_ANSI_U, Key_U }, + { kVK_ANSI_V, Key_V }, + { kVK_ANSI_W, Key_W }, + { kVK_ANSI_X, Key_X }, + { kVK_ANSI_Y, Key_Y }, + { kVK_ANSI_Z, Key_Z }, + }; + CKeyboardMac::CKeyboardMac(QObject *parent) : - IKeyboard(parent), - m_mode(Mode_Nominal) + IKeyboard(parent) { } @@ -34,44 +74,47 @@ namespace BlackInput bool CKeyboardMac::init() { bool accessibilityEnabled = false; - if (AXIsProcessTrustedWithOptions != NULL) { + if (AXIsProcessTrustedWithOptions != NULL) + { // 10.9 and later - const void * keys[] = { kAXTrustedCheckOptionPrompt }; - const void * values[] = { kCFBooleanTrue }; + const void *keys[] = { kAXTrustedCheckOptionPrompt }; + const void *values[] = { kCFBooleanTrue }; CFDictionaryRef options = CFDictionaryCreate( - kCFAllocatorDefault, - keys, - values, - sizeof(keys) / sizeof(*keys), - &kCFCopyStringDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); + kCFAllocatorDefault, + keys, + values, + sizeof(keys) / sizeof(*keys), + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); accessibilityEnabled = AXIsProcessTrustedWithOptions(options); } - else { + else + { // 10.8 and older accessibilityEnabled = AXAPIEnabled(); } - if (!accessibilityEnabled) { + if (!accessibilityEnabled) + { QMessageBox msgBox; msgBox.setText("In order to enable hotkeys first add Swift to the list of apps allowed to " - "control your computer in System Preferences / Security & Privacy / Privacy / Accessiblity and then restart Swift."); + "control your computer in System Preferences / Security & Privacy / Privacy / Accessiblity and then restart Swift."); msgBox.exec(); return false; } - CGEventMask eventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventKeyUp) | (1 <(CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode)); - bool isFinished = false; - if (type == kCGEventKeyDown) { - m_pressedKey.setKey(CKeyMappingMac::convertToKey(vkcode)); - } else if (type == kCGEventKeyUp) { - m_pressedKey.setKey(Qt::Key_unknown); - isFinished = true; - } else if (type == kCGEventFlagsChanged) { - - // m_pressedKey.removeAllModifiers(); - - CGEventFlags f = CGEventGetFlags(event); - qDebug() << "hier"; - - if ((f & kCGEventFlagMaskShift) == kCGEventFlagMaskShift) { - qDebug() << "shift"; - if (vkcode == 56) { - m_pressedKey.addModifier(CKeyboardKey::ModifierShiftLeft); - } else if (vkcode == 60) { - m_pressedKey.addModifier(CKeyboardKey::ModifierShiftRight); - } - } else { - m_pressedKey.removeModifier(CKeyboardKey::ModifierShiftLeft); - m_pressedKey.removeModifier(CKeyboardKey::ModifierShiftRight); - } - - if ((f & kCGEventFlagMaskControl) == kCGEventFlagMaskControl) { - qDebug() << "ctrl"; - // at least on the mac wireless keyboard there is no right ctrl key - if (vkcode == 59) { - m_pressedKey.addModifier(CKeyboardKey::ModifierCtrlLeft); - } - } else { - m_pressedKey.removeModifier(CKeyboardKey::ModifierCtrlLeft); - } - - if ((f & kCGEventFlagMaskAlternate) == kCGEventFlagMaskAlternate) { - qDebug() << "alt"; - if (vkcode == 58) { - m_pressedKey.addModifier(CKeyboardKey::ModifierAltLeft); - } else if (vkcode == 61) { - m_pressedKey.addModifier(CKeyboardKey::ModifierAltRight); - } - } else { - m_pressedKey.removeModifier(CKeyboardKey::ModifierAltLeft); - m_pressedKey.removeModifier(CKeyboardKey::ModifierAltRight); - } - } - - if (lastPressedKey == m_pressedKey) - return; - - if (m_mode == Mode_Capture) + if (type == kCGEventKeyDown) { - if (isFinished) + auto key = convertToKey(vkcode); + if (key == Key_Unknown) { return; } + m_keyCombination.addKeyboardKey(key); + } + else if (type == kCGEventKeyUp) + { + auto key = convertToKey(vkcode); + if (key == Key_Unknown) { return; } + m_keyCombination.removeKeyboardKey(key); + } + else if (type == kCGEventFlagsChanged) + { + CGEventFlags f = CGEventGetFlags(event); + + if ((f & kCGEventFlagMaskShift) == kCGEventFlagMaskShift) { - sendCaptureNotification(lastPressedKey, true); - m_mode = Mode_Nominal; + if (vkcode == 56) + { + m_keyCombination.addKeyboardKey(Key_ShiftLeft); + } + else if (vkcode == 60) + { + m_keyCombination.addKeyboardKey(Key_ShiftRight); + } } else { - sendCaptureNotification(m_pressedKey, false); + m_keyCombination.removeKeyboardKey(Key_ShiftLeft); + m_keyCombination.removeKeyboardKey(Key_ShiftRight); + } + + if ((f & kCGEventFlagMaskControl) == kCGEventFlagMaskControl) + { + // at least on the mac wireless keyboard there is no right ctrl key + if (vkcode == 59) + { + m_keyCombination.addKeyboardKey(Key_ControlLeft); + } + } + else + { + m_keyCombination.removeKeyboardKey(Key_ControlLeft); + } + + if ((f & kCGEventFlagMaskAlternate) == kCGEventFlagMaskAlternate) + { + if (vkcode == 58) + { + m_keyCombination.addKeyboardKey(Key_AltLeft); + } + else if (vkcode == 61) + { + m_keyCombination.addKeyboardKey(Key_AltRight); + } + } + else + { + m_keyCombination.removeKeyboardKey(Key_AltLeft); + m_keyCombination.removeKeyboardKey(Key_AltRight); } } - else + + if (oldCombination == m_keyCombination) { - if (m_listMonitoredKeys.contains(lastPressedKey)) emit keyUp(lastPressedKey); - if (m_listMonitoredKeys.contains(m_pressedKey)) emit keyDown(m_pressedKey); + emit keyCombinationChanged(m_keyCombination); } } - void CKeyboardMac::sendCaptureNotification(const CKeyboardKey &key, bool isFinished) + KeyCode CKeyboardMac::convertToKey(int keyCode) { - if (isFinished) - emit keySelectionFinished(key); - else - emit keySelectionChanged(key); + return keyMapping.value(keyCode, Key_Unknown); } CGEventRef CKeyboardMac::myCGEventCallback(CGEventTapProxy, - CGEventType type, - CGEventRef event, - void *) + CGEventType type, + CGEventRef event, + void *refcon) { - CKeyboardMac *keyboardMac = qobject_cast(IKeyboard::getInstance()); + CKeyboardMac *keyboardMac = static_cast(refcon); keyboardMac->processKeyEvent(type, event); - // send event to next application - return event; + // send event to next application + return event; } } diff --git a/src/blackinput/osx/keymapping_mac.h b/src/blackinput/osx/keymapping_mac.h deleted file mode 100644 index 02365bb29..000000000 --- a/src/blackinput/osx/keymapping_mac.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright (C) 2015 - * 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. - */ - -//! \file - -#ifndef BLACKINPUT_KEYMAPPING_MAC_H -#define BLACKINPUT_KEYMAPPING_MAC_H - -#include "blackmisc/hardware/keyboardkey.h" - -namespace BlackInput -{ - //! \brief This class provides methods to map between Mac OS X virtual keys and CKeyboardKey - class CKeyMappingMac - { - public: - /*! - * \brief Convert to Qt key - * \param virtualKey - * \return - */ - static Qt::Key convertToKey(unsigned int virtualKey); - }; - -} // namespace BlackInput - -#endif // KEYMAPPING_MAC_H diff --git a/src/blackinput/osx/keymapping_mac.mm b/src/blackinput/osx/keymapping_mac.mm deleted file mode 100644 index caf32d066..000000000 --- a/src/blackinput/osx/keymapping_mac.mm +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright (C) 2015 - * 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 "keymapping_mac.h" -#include -#include - -using namespace BlackMisc::Hardware; - -namespace BlackInput -{ - Qt::Key CKeyMappingMac::convertToKey(unsigned int virtualKey) - { - switch (virtualKey) - { - case kVK_ANSI_0: return Qt::Key_0; - case kVK_ANSI_1: return Qt::Key_1; - case kVK_ANSI_2: return Qt::Key_2; - case kVK_ANSI_3: return Qt::Key_3; - case kVK_ANSI_4: return Qt::Key_4; - case kVK_ANSI_5: return Qt::Key_5; - case kVK_ANSI_6: return Qt::Key_6; - case kVK_ANSI_7: return Qt::Key_7; - case kVK_ANSI_8: return Qt::Key_8; - case kVK_ANSI_9: return Qt::Key_9; - case kVK_ANSI_A: return Qt::Key_A; - case kVK_ANSI_B: return Qt::Key_B; - case kVK_ANSI_C: return Qt::Key_C; - case kVK_ANSI_D: return Qt::Key_D; - case kVK_ANSI_E: return Qt::Key_E; - case kVK_ANSI_F: return Qt::Key_F; - case kVK_ANSI_G: return Qt::Key_G; - case kVK_ANSI_H: return Qt::Key_H; - case kVK_ANSI_I: return Qt::Key_I; - case kVK_ANSI_J: return Qt::Key_J; - case kVK_ANSI_K: return Qt::Key_K; - case kVK_ANSI_L: return Qt::Key_L; - case kVK_ANSI_M: return Qt::Key_M; - case kVK_ANSI_N: return Qt::Key_N; - case kVK_ANSI_O: return Qt::Key_O; - case kVK_ANSI_P: return Qt::Key_P; - case kVK_ANSI_Q: return Qt::Key_Q; - case kVK_ANSI_R: return Qt::Key_R; - case kVK_ANSI_S: return Qt::Key_S; - case kVK_ANSI_T: return Qt::Key_T; - case kVK_ANSI_U: return Qt::Key_U; - case kVK_ANSI_V: return Qt::Key_V; - case kVK_ANSI_W: return Qt::Key_W; - case kVK_ANSI_X: return Qt::Key_X; - case kVK_ANSI_Y: return Qt::Key_Y; - case kVK_ANSI_Z: return Qt::Key_Z; - default: return Qt::Key_unknown; - } - } - -} // namespace BlackInput diff --git a/src/blackinput/win/joystick_windows.cpp b/src/blackinput/win/joystick_windows.cpp index f662ec545..f9f626765 100644 --- a/src/blackinput/win/joystick_windows.cpp +++ b/src/blackinput/win/joystick_windows.cpp @@ -17,13 +17,13 @@ // handling in the second branch. using namespace BlackMisc; -using namespace BlackMisc::Hardware; +using namespace BlackMisc::Input; namespace BlackInput { - const TCHAR *CJoystickWindows::m_helperWindowClassName = TEXT("SDLHelperWindowInputCatcher"); - const TCHAR *CJoystickWindows::m_helperWindowName = TEXT("SDLHelperWindowInputMsgWindow"); + const TCHAR *CJoystickWindows::m_helperWindowClassName = TEXT("HelperWindow"); + const TCHAR *CJoystickWindows::m_helperWindowName = TEXT("JoystickCatcherWindow"); ATOM CJoystickWindows::m_helperWindowClass = 0; HWND CJoystickWindows::m_helperWindow = nullptr; @@ -43,17 +43,6 @@ namespace BlackInput CoUninitialize(); } - void CJoystickWindows::startCapture() - { - // TODO - } - - void CJoystickWindows::triggerButton(const CJoystickButton button, bool isPressed) - { - if (!isPressed) emit buttonUp(button); - else emit buttonDown(button); - } - void CJoystickWindows::timerEvent(QTimerEvent * /* event */) { pollDeviceState(); @@ -207,23 +196,13 @@ namespace BlackInput void CJoystickWindows::updateAndSendButtonStatus(qint32 buttonIndex, bool isPressed) { - if (isPressed) + BlackMisc::Input::CHotkeyCombination oldCombination(m_buttonCombination); + if (isPressed) { m_buttonCombination.addJoystickButton(buttonIndex); } + else { m_buttonCombination.removeJoystickButton(buttonIndex); } + + if (oldCombination != m_buttonCombination) { - if (!m_pressedButtons.contains(buttonIndex)) - { - CJoystickButton joystickButton(buttonIndex); - emit buttonDown(joystickButton); - m_pressedButtons.push_back(buttonIndex); - } - } - else - { - if (m_pressedButtons.contains(buttonIndex)) - { - CJoystickButton joystickButton(buttonIndex); - emit buttonUp(joystickButton); - m_pressedButtons.remove(buttonIndex); - } + emit buttonCombinationChanged(m_buttonCombination); } } @@ -260,7 +239,7 @@ namespace BlackInput m_directInputDevice->Acquire(); if (FAILED(hr = m_directInputDevice->Poll())) { - // FIXME: print error message + CLogMessage(this).warning("DirectInput error code: ") << hr; return hr; } } @@ -273,7 +252,7 @@ namespace BlackInput m_directInputDevice->Acquire(); if (FAILED(hr = m_directInputDevice->GetDeviceState(sizeof(DIJOYSTATE2), &state))) { - // FIXME: print error message + CLogMessage(this).warning("DirectInput error code: ") << hr; return hr; } } diff --git a/src/blackinput/win/joystick_windows.h b/src/blackinput/win/joystick_windows.h index 2d5aa8af6..2660e8878 100644 --- a/src/blackinput/win/joystick_windows.h +++ b/src/blackinput/win/joystick_windows.h @@ -14,7 +14,7 @@ #include "blackinput/blackinputexport.h" #include "blackinput/joystick.h" -#include "blackmisc/hardware/joystickbutton.h" +#include "blackmisc/input/joystickbutton.h" #include "blackmisc/collection.h" #include @@ -62,12 +62,6 @@ namespace BlackInput //! \brief Destructor virtual ~CJoystickWindows(); - //! \copydoc IJoystick::startCapture() - virtual void startCapture() override; - - //! \copydoc IJoystick::triggerButton() - virtual void triggerButton(const BlackMisc::Hardware::CJoystickButton button, bool isPressed) override; - protected: //! Timer based updates @@ -116,9 +110,8 @@ namespace BlackInput QList m_availableJoystickDevices; //!< List of found and available joystick devices QList m_joystickDeviceInputs; //!< List of available device buttons - BlackMisc::CCollection m_pressedButtons; //!< Collection of pressed buttons - IJoystick::Mode m_mode = ModeNominal; //!< Current working mode + BlackMisc::Input::CHotkeyCombination m_buttonCombination; static const WCHAR *m_helperWindowClassName; //!< Helper window class name static const WCHAR *m_helperWindowName; //!< Helper window name diff --git a/src/blackinput/win/keyboard_windows.cpp b/src/blackinput/win/keyboard_windows.cpp index acf09cbd3..b1c613bc2 100644 --- a/src/blackinput/win/keyboard_windows.cpp +++ b/src/blackinput/win/keyboard_windows.cpp @@ -4,17 +4,63 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "keyboard_windows.h" -#include "keymapping_windows.h" -#include -using namespace BlackMisc::Hardware; +using namespace BlackMisc::Input; namespace BlackInput { + + static QHash keyMapping + { + { '0', Key_0 }, + { '1', Key_1 }, + { '2', Key_2 }, + { '3', Key_3 }, + { '4', Key_4 }, + { '5', Key_5 }, + { '6', Key_6 }, + { '7', Key_7 }, + { '8', Key_8 }, + { '9', Key_9 }, + { 'A', Key_A }, + { 'B', Key_B }, + { 'C', Key_C }, + { 'D', Key_D }, + { 'E', Key_E }, + { 'F', Key_F }, + { 'G', Key_G }, + { 'H', Key_H }, + { 'I', Key_I }, + { 'J', Key_J }, + { 'K', Key_K }, + { 'L', Key_L }, + { 'M', Key_M }, + { 'N', Key_N }, + { 'O', Key_O }, + { 'P', Key_P }, + { 'Q', Key_Q }, + { 'R', Key_R }, + { 'S', Key_S }, + { 'T', Key_T }, + { 'U', Key_U }, + { 'V', Key_V }, + { 'W', Key_W }, + { 'X', Key_X }, + { 'Y', Key_Y }, + { 'Z', Key_Z }, + { VK_LSHIFT, Key_ShiftLeft }, + { VK_RSHIFT, Key_ShiftRight }, + { VK_LCONTROL, Key_ControlLeft }, + { VK_RCONTROL, Key_ControlRight }, + { VK_LMENU, Key_AltLeft }, + { VK_RMENU, Key_AltRight }, + }; + + static CKeyboardWindows *g_keyboardWindows = nullptr; + CKeyboardWindows::CKeyboardWindows(QObject *parent) : IKeyboard(parent), - m_keyboardHook(nullptr), - m_mode(Mode_Nominal) + m_keyboardHook(nullptr) { } @@ -26,103 +72,42 @@ namespace BlackInput bool CKeyboardWindows::init() { + Q_ASSERT_X(g_keyboardWindows == nullptr, "CKeyboardWindows::init", "Windows supports only one keyboard instance. Cannot initialize a second one!"); + g_keyboardWindows = this; m_keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, CKeyboardWindows::keyboardProc, GetModuleHandle(NULL), 0); return true; } - void CKeyboardWindows::setKeysToMonitor(const CKeyboardKeyList &keylist) - { - m_listMonitoredKeys = keylist; - } - - void CKeyboardWindows::startCapture(bool ignoreNextKey) - { - m_mode = Mode_Capture; - m_ignoreNextKey = ignoreNextKey; - m_pressedKey.setKeyObject(CKeyboardKey()); - } - - void CKeyboardWindows::triggerKey(const CKeyboardKey &key, bool isPressed) - { - if(!isPressed) emit keyUp(key); - else emit keyDown(key); - } - void CKeyboardWindows::processKeyEvent(WPARAM vkcode, uint event) { - BlackMisc::Hardware::CKeyboardKey lastPressedKey = m_pressedKey; - if (m_ignoreNextKey) - { - m_ignoreNextKey = false; - return; - } - - bool isFinished = false; + BlackMisc::Input::CHotkeyCombination oldCombination(m_keyCombination); if ((event == WM_KEYDOWN) || (event == WM_SYSKEYDOWN)) { - if (CKeyMappingWindows::isModifier(vkcode)) - m_pressedKey.addModifier(CKeyMappingWindows::convertToModifier(vkcode)); - else - { - m_pressedKey.setKey(CKeyMappingWindows::convertToKey(vkcode)); - } + auto key = keyMapping.value(vkcode); + if (key == Key_Unknown) { return; } + m_keyCombination.addKeyboardKey(CKeyboardKey(key)); } else if ((event == WM_KEYUP) || (event == WM_SYSKEYUP) ) { - if (CKeyMappingWindows::isModifier(vkcode)) - m_pressedKey.removeModifier(CKeyMappingWindows::convertToModifier(vkcode)); - else - { - m_pressedKey.setKey(Qt::Key_unknown); - } - - isFinished = true; + auto key = keyMapping.value(vkcode); + if (key == Key_Unknown) { return; } + m_keyCombination.removeKeyboardKey(CKeyboardKey(key)); } - if (lastPressedKey == m_pressedKey) - return; - -#ifdef DEBUG_KEYBOARD_WINDOWS - qDebug() << "Virtual key: " << vkcode; -#endif - if (m_mode == Mode_Capture) + if (oldCombination != m_keyCombination) { - if (isFinished) - { - sendCaptureNotification(lastPressedKey, true); - m_mode = Mode_Nominal; - } - else - { - sendCaptureNotification(m_pressedKey, false); - } + emit keyCombinationChanged(m_keyCombination); } - else - { - if (m_listMonitoredKeys.contains(lastPressedKey)) emit keyUp(lastPressedKey); - if (m_listMonitoredKeys.contains(m_pressedKey)) emit keyDown(m_pressedKey); - } - } - - void CKeyboardWindows::sendCaptureNotification(const CKeyboardKey &key, bool isFinished) - { - if (isFinished) - emit keySelectionFinished(key); - else - emit keySelectionChanged(key); } LRESULT CALLBACK CKeyboardWindows::keyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { - // This is the reason why we have to use singleton pattern. We cannot pass a object pointer to - // keyboardProc. - CKeyboardWindows *keyboardWindows = qobject_cast(IKeyboard::getInstance()); if (nCode == HC_ACTION) { KBDLLHOOKSTRUCT *keyboardEvent =reinterpret_cast(lParam); WPARAM vkCode = keyboardEvent->vkCode; - keyboardWindows->processKeyEvent(vkCode, wParam); + g_keyboardWindows->processKeyEvent(vkCode, wParam); } - return CallNextHookEx(keyboardWindows->keyboardHook(), nCode, wParam, lParam); + return CallNextHookEx(g_keyboardWindows->keyboardHook(), nCode, wParam, lParam); } } diff --git a/src/blackinput/win/keyboard_windows.h b/src/blackinput/win/keyboard_windows.h index 0a3f759ba..ebb689312 100644 --- a/src/blackinput/win/keyboard_windows.h +++ b/src/blackinput/win/keyboard_windows.h @@ -12,8 +12,8 @@ #include "blackinput/blackinputexport.h" #include "blackinput/keyboard.h" -#include "blackmisc/hardware/keyboardkey.h" -#include "blackmisc/hardware/keyboardkeylist.h" +#include "blackmisc/input/keyboardkey.h" +#include "blackmisc/input/keyboardkeylist.h" #include #ifndef NOMINMAX #define NOMINMAX @@ -23,7 +23,6 @@ namespace BlackInput { //! \brief Windows implemenation of IKeyboard using hook procedure - //! \todo Change QHash to a CCollection object class BLACKINPUT_EXPORT CKeyboardWindows : public IKeyboard { Q_OBJECT @@ -38,15 +37,6 @@ namespace BlackInput //! \brief Destructor virtual ~CKeyboardWindows(); - //! \copydoc IKeyboard::setKeysToMonitor() - virtual void setKeysToMonitor(const BlackMisc::Hardware::CKeyboardKeyList &keylist) override; - - //! \copydoc IKeyboard::selectKey() - virtual void startCapture(bool ignoreNextKey = false) override; - - //! \copydoc IKeyboard::triggerKey() - virtual void triggerKey(const BlackMisc::Hardware::CKeyboardKey &key, bool isPressed) override; - //! \brief Keyboard hook handle HHOOK keyboardHook() const { return m_keyboardHook; } @@ -65,13 +55,6 @@ namespace BlackInput //! \brief Constructor CKeyboardWindows(QObject *parent = nullptr); - /*! - * \brief Constructor - * \param keySet - * \param isFinished - */ - void sendCaptureNotification(const BlackMisc::Hardware::CKeyboardKey &key, bool isFinished); - void addKey(WPARAM vkcode); void removeKey(WPARAM vkcode); @@ -85,11 +68,8 @@ namespace BlackInput static LRESULT CALLBACK keyboardProc(int nCode, WPARAM wParam, LPARAM lParam); - BlackMisc::Hardware::CKeyboardKeyList m_listMonitoredKeys; //!< Registered keys - BlackMisc::Hardware::CKeyboardKey m_pressedKey; //!< Set of virtual keys pressed in the last cycle - bool m_ignoreNextKey; //!< Is true if the next key needs to be ignored + BlackMisc::Input::CHotkeyCombination m_keyCombination; //!< Set of virtual keys pressed in the last cycle HHOOK m_keyboardHook; //!< Keyboard hook handle - Mode m_mode; //!< Operation mode }; } diff --git a/src/blackinput/win/keymapping_windows.cpp b/src/blackinput/win/keymapping_windows.cpp deleted file mode 100644 index 44cdc5b71..000000000 --- a/src/blackinput/win/keymapping_windows.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2013 VATSIM Community / contributors - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "keymapping_windows.h" -#include - -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include - -using namespace BlackMisc::Hardware; - -namespace BlackInput -{ - Qt::Key CKeyMappingWindows::convertToKey(WPARAM virtualKey) - { - switch (virtualKey) - { - case '0': return Qt::Key_0; break; - case '1': return Qt::Key_1; break; - case '2': return Qt::Key_2; break; - case '3': return Qt::Key_3; break; - case '4': return Qt::Key_4; break; - case '5': return Qt::Key_5; break; - case '6': return Qt::Key_6; break; - case '7': return Qt::Key_7; break; - case '8': return Qt::Key_8; break; - case '9': return Qt::Key_9; break; - case 'A': return Qt::Key_A; break; - case 'B': return Qt::Key_B; break; - case 'C': return Qt::Key_C; break; - case 'D': return Qt::Key_D; break; - case 'E': return Qt::Key_E; break; - case 'F': return Qt::Key_F; break; - case 'G': return Qt::Key_G; break; - case 'H': return Qt::Key_H; break; - case 'I': return Qt::Key_I; break; - case 'J': return Qt::Key_J; break; - case 'K': return Qt::Key_K; break; - case 'L': return Qt::Key_L; break; - case 'M': return Qt::Key_M; break; - case 'N': return Qt::Key_N; break; - case 'O': return Qt::Key_O; break; - case 'P': return Qt::Key_P; break; - case 'Q': return Qt::Key_Q; break; - case 'R': return Qt::Key_R; break; - case 'S': return Qt::Key_S; break; - case 'T': return Qt::Key_T; break; - case 'U': return Qt::Key_U; break; - case 'V': return Qt::Key_V; break; - case 'W': return Qt::Key_W; break; - case 'X': return Qt::Key_X; break; - case 'Y': return Qt::Key_Y; break; - case 'Z': return Qt::Key_Z; break; - default: return Qt::Key_unknown; break; - } - } - - CKeyboardKey::Modifier CKeyMappingWindows::convertToModifier(WPARAM virtualKey) - { - switch (virtualKey) - { - case VK_LSHIFT: return CKeyboardKey::ModifierShiftLeft; break; - case VK_RSHIFT: return CKeyboardKey::ModifierShiftRight; break; - case VK_LCONTROL: return CKeyboardKey::ModifierCtrlLeft; break; - case VK_RCONTROL: return CKeyboardKey::ModifierCtrlRight; break; - case VK_LMENU: return CKeyboardKey::ModifierAltLeft; break; - case VK_RMENU: return CKeyboardKey::ModifierAltRight; break; - default: return CKeyboardKey::ModifierNone; break; - } - } - - bool CKeyMappingWindows::isModifier(WPARAM vkcode) - { - switch (vkcode) - { - case VK_LSHIFT: - case VK_RSHIFT: - case VK_LCONTROL: - case VK_RCONTROL: - case VK_LMENU: - case VK_RMENU: - case VK_LWIN: - case VK_RWIN: - return true; - default: return false; - } - } - -} // namespace BlackInput diff --git a/src/blackinput/win/keymapping_windows.h b/src/blackinput/win/keymapping_windows.h deleted file mode 100644 index 8ef5006a2..000000000 --- a/src/blackinput/win/keymapping_windows.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (C) 2013 VATSIM Community / contributors - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - -#ifndef BLACKINPUT_KEYMAPPING_WINDOWS_H -#define BLACKINPUT_KEYMAPPING_WINDOWS_H - -#include "blackinput/blackinputexport.h" -#include "blackmisc/hardware/keyboardkey.h" -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include - -namespace BlackInput -{ - //! \brief This class provides methods to map between windows virtual keys and CKeyboardKey - class BLACKINPUT_EXPORT CKeyMappingWindows - { - public: - /*! - * \brief Converts a set of windows virtual keys to a CKeySet object - * \param virtualKey - * \return - */ - static BlackMisc::Hardware::CKeyboardKey::Modifier convertToModifier(WPARAM virtualKey); - - /*! - * \brief Convert to Qt key - * \param virtualKey - * \return - */ - static Qt::Key convertToKey(WPARAM virtualKey); - - /*! - * \brief Checks if its a modifier key - * \param vkcode - * \return - */ - static bool isModifier(WPARAM vkcode); - }; - -} // namespace BlackInput -#endif // guard diff --git a/src/swiftgui_standard/swiftguistd.cpp b/src/swiftgui_standard/swiftguistd.cpp index 7d45abe97..8244a572c 100644 --- a/src/swiftgui_standard/swiftguistd.cpp +++ b/src/swiftgui_standard/swiftguistd.cpp @@ -36,7 +36,7 @@ using namespace BlackMisc::PhysicalQuantities; using namespace BlackMisc::Geo; using namespace BlackMisc::Settings; using namespace BlackMisc::Audio; -using namespace BlackMisc::Hardware; +using namespace BlackMisc::Input; /* * Constructor @@ -375,26 +375,6 @@ void SwiftGuiStd::ps_toggleWindowVisibility() } } -void SwiftGuiStd::ps_registerHotkeyFunctions() -{ - CInputManager *m_inputManager = BlackCore::CInputManager::getInstance(); - - m_inputManager->registerHotkeyFunc(CHotkeyFunction::Opacity50(), this, [ this ](bool isPressed) - { - if (isPressed) this->ps_onChangedWindowOpacity(50); - }); - - m_inputManager->registerHotkeyFunc(CHotkeyFunction::Opacity100(), this, [ this ](bool isPressed) - { - if (isPressed) this->ps_onChangedWindowOpacity(100); - }); - - m_inputManager->registerHotkeyFunc(CHotkeyFunction::ToogleWindowsStayOnTop(), this, [ this ](bool isPressed) - { - if (isPressed) this->ps_toogleWindowStayOnTop(); - }); -} - void SwiftGuiStd::ps_onStyleSheetsChanged() { this->initStyleSheet(); diff --git a/src/swiftgui_standard/swiftguistd.h b/src/swiftgui_standard/swiftguistd.h index 88bad7985..0760c1936 100644 --- a/src/swiftgui_standard/swiftguistd.h +++ b/src/swiftgui_standard/swiftguistd.h @@ -18,7 +18,6 @@ #include "guimodeenums.h" #include "blackcore/context_all_interfaces.h" -#include "blackcore/input_manager.h" #include "blackgui/components/enableforruntime.h" #include "blackgui/components/infowindowcomponent.h" #include "blackgui/components/maininfoareacomponent.h" @@ -113,7 +112,6 @@ private: bool m_init = false; BlackGui::Components::CInfoWindowComponent *m_compInfoWindow = nullptr; //!< the info window (popup BlackGui::CManagedStatusBar m_statusBar; - BlackInput::IKeyboard *m_keyboard = nullptr; //!< hotkeys BlackMisc::CLogSubscriber m_logSubscriber { this, &SwiftGuiStd::ps_displayStatusMessageInGui }; // contexts @@ -239,9 +237,6 @@ private slots: //! Toggle window visibility void ps_toggleWindowVisibility(); - //! Set the hotkey functions - void ps_registerHotkeyFunctions(); - //! Style sheet has been changed void ps_onStyleSheetsChanged(); diff --git a/src/swiftgui_standard/swiftguistd_init.cpp b/src/swiftgui_standard/swiftguistd_init.cpp index 180e2ca5a..b8ca73f06 100644 --- a/src/swiftgui_standard/swiftguistd_init.cpp +++ b/src/swiftgui_standard/swiftguistd_init.cpp @@ -125,9 +125,6 @@ void SwiftGuiStd::init(const CRuntimeConfig &runtimeConfig) this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(CProject::swiftVersionString()); this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(CProject::compiledInfo()); - // hotkeys - this->ps_registerHotkeyFunctions(); - // update timers this->startUpdateTimersWhenConnected();