140 lines
3.6 KiB
C++
140 lines
3.6 KiB
C++
// Copyright 2007-2023 The Mumble Developers. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license
|
|
// that can be found in the LICENSE file at the root of the
|
|
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
|
|
|
|
#ifndef MUMBLE_MUMBLE_GLOBALSHORTCUT_WIN_H_
|
|
#define MUMBLE_MUMBLE_GLOBALSHORTCUT_WIN_H_
|
|
|
|
#include "GlobalShortcut.h"
|
|
|
|
#ifdef USE_XBOXINPUT
|
|
# include "XboxInput.h"
|
|
#endif
|
|
|
|
#include <condition_variable>
|
|
#include <memory>
|
|
#include <unordered_map>
|
|
|
|
#include <gsl/span>
|
|
|
|
#include <rigtorp/SPSCQueue.h>
|
|
|
|
#ifdef USE_GKEY
|
|
class GKeyLibrary;
|
|
#endif
|
|
|
|
class GlobalShortcutWin : public GlobalShortcutEngine {
|
|
Q_OBJECT
|
|
Q_DISABLE_COPY(GlobalShortcutWin)
|
|
|
|
public:
|
|
static void registerMetaTypes();
|
|
|
|
/// @param oldShortcuts List of shortcuts to migrate.
|
|
/// @returns List of shortcuts in the new format.
|
|
static QList< Shortcut > migrateSettings(const QList< Shortcut > &oldShortcuts);
|
|
|
|
/// Inject a native Windows raw input message into GlobalShortcutWin's
|
|
/// thread. This method is meant to be called from the main thread
|
|
/// to pass native Windows keyboard messages to GlobalShortcutWin.
|
|
///
|
|
/// @param msg The raw input handle to inject into GlobalShortcutWin.
|
|
void injectRawInputMessage(HRAWINPUT handle);
|
|
|
|
ButtonInfo buttonInfo(const QVariant &button) override;
|
|
void run() override;
|
|
|
|
GlobalShortcutWin();
|
|
~GlobalShortcutWin() override;
|
|
public slots:
|
|
void deviceRemoved(const HANDLE deviceHandle);
|
|
|
|
protected:
|
|
class MsgRaw {
|
|
public:
|
|
enum Type : uint8_t { Hid, Keyboard, Mouse };
|
|
|
|
constexpr Type type() { return m_type; };
|
|
|
|
protected:
|
|
MsgRaw(const Type type) : m_type(type) {}
|
|
|
|
private:
|
|
Type m_type;
|
|
};
|
|
|
|
class MsgHid : public MsgRaw {
|
|
public:
|
|
using RawReports = gsl::span< const BYTE >;
|
|
|
|
MsgHid(HANDLE deviceHandle, const RawReports rawReports, const DWORD reportSize)
|
|
: MsgRaw(Hid), deviceHandle(deviceHandle), reports(rawReports.size()), reportSize(reportSize) {
|
|
memcpy(reports.data(), rawReports.data(), reports.size());
|
|
}
|
|
|
|
HANDLE deviceHandle;
|
|
std::vector< char > reports;
|
|
DWORD reportSize;
|
|
};
|
|
|
|
class MsgKeyboard : public MsgRaw {
|
|
public:
|
|
MsgKeyboard(const USHORT flags, const USHORT scanCode, const USHORT virtualKey)
|
|
: MsgRaw(Keyboard), flags(flags), scanCode(scanCode), virtualKey(virtualKey) {}
|
|
|
|
USHORT flags;
|
|
USHORT scanCode;
|
|
USHORT virtualKey;
|
|
};
|
|
|
|
class MsgMouse : public MsgRaw {
|
|
public:
|
|
MsgMouse(const USHORT buttonFlags) : MsgRaw(Mouse), buttonFlags(buttonFlags) {}
|
|
|
|
USHORT buttonFlags;
|
|
};
|
|
|
|
struct Device {
|
|
std::string name;
|
|
std::string prefix;
|
|
std::vector< uint8_t > data;
|
|
std::vector< bool > buttons;
|
|
std::pair< uint16_t, uint16_t > usageRange;
|
|
#ifdef USE_XBOXINPUT
|
|
bool xinput;
|
|
Device() : xinput(false){};
|
|
#endif
|
|
};
|
|
|
|
void processMsgHid(MsgHid &msg);
|
|
void processMsgKeyboard(MsgKeyboard &msg);
|
|
void processMsgMouse(const MsgMouse &msg);
|
|
void processOther();
|
|
|
|
std::condition_variable m_condVar;
|
|
|
|
rigtorp::SPSCQueue< std::unique_ptr< MsgRaw > > m_msgQueue;
|
|
|
|
typedef std::unordered_map< HANDLE, Device > DeviceMap;
|
|
DeviceMap m_devices;
|
|
#ifdef USE_XBOXINPUT
|
|
std::unique_ptr< XboxInput > m_xinput;
|
|
/// Holds the number of XInput devices available on the system.
|
|
/// It is filled out by addDevice().
|
|
uint8_t m_xinputDevices;
|
|
/// Holds the last packet number that was processed.
|
|
/// Any new data queried for a device is only valid
|
|
/// if the packet number is different than last time we queried it.
|
|
uint32_t m_xinputLastPacket[XBOXINPUT_MAX_DEVICES];
|
|
|
|
static bool xinputIsPressed(const uint8_t bit, const XboxInputState &state);
|
|
#endif
|
|
#ifdef USE_GKEY
|
|
std::unique_ptr< GKeyLibrary > m_gkey;
|
|
#endif
|
|
DeviceMap::iterator addDevice(const HANDLE deviceHandle);
|
|
};
|
|
|
|
#endif
|