From 8dca727968bf64c8aa89cce09172f101c2ade069 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 11:44:42 +0100 Subject: shortcuts: separate keybinding worker to another file --- opentrack/keybinding-worker.cpp | 112 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 opentrack/keybinding-worker.cpp (limited to 'opentrack/keybinding-worker.cpp') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp new file mode 100644 index 00000000..29b2cf9f --- /dev/null +++ b/opentrack/keybinding-worker.cpp @@ -0,0 +1,112 @@ +/* Copyright (c) 2014-2015, Stanislaw Halik + + * Permission to use, copy, modify, and/or distribute this + * software for any purpose with or without fee is hereby granted, + * provided that the above copyright notice and this permission + * notice appear in all copies. + */ + +#include "keybinding-worker.hpp" + +#if defined(_WIN32) +# include +# include +# include + +KeybindingWorker::~KeybindingWorker() { + should_quit = true; + wait(); + if (dinkeyboard) { + dinkeyboard->Unacquire(); + dinkeyboard->Release(); + } + if (din) + din->Release(); +} + +KeybindingWorker::KeybindingWorker(std::function receiver, WId h) : + should_quit(true), receiver(receiver) +{ + HWND handle = reinterpret_cast(h); + + if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { + qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); + return; + } + if (din->CreateDevice(GUID_SysKeyboard, &dinkeyboard, NULL) != DI_OK) { + din->Release(); + din = 0; + qDebug() << "setup CreateDevice function failed!" << GetLastError(); + return; + } + if (dinkeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) { + qDebug() << "setup SetDataFormat function failed!" << GetLastError(); + dinkeyboard->Release(); + dinkeyboard = 0; + din->Release(); + din = 0; + return; + } + if (dinkeyboard->SetCooperativeLevel((HWND) handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { + dinkeyboard->Release(); + din->Release(); + din = 0; + dinkeyboard = 0; + qDebug() << "setup SetCooperativeLevel function failed!" << GetLastError(); + return; + } + if (dinkeyboard->Acquire() != DI_OK) + { + dinkeyboard->Release(); + din->Release(); + din = 0; + dinkeyboard = 0; + qDebug() << "setup dinkeyboard Acquire failed!" << GetLastError(); + return; + } + should_quit = false; +} + +void KeybindingWorker::run() { + BYTE keystate[256]; + + while (!should_quit) + { + if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) { + qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); + Sleep(25); + continue; + } + + QMutexLocker l(&mtx); + + for (int i = 0; i < 256; i++) + { + Key k; + if (keystate[i] & 0x80) + { + switch (i) + { + case DIK_LCONTROL: + case DIK_LSHIFT: + case DIK_LALT: + case DIK_RCONTROL: + case DIK_RSHIFT: + case DIK_RALT: + break; + default: + k.shift = !!(keystate[DIK_LSHIFT] & 0x80) || !!(keystate[DIK_RSHIFT] & 0x80); + k.alt = !!(keystate[DIK_LALT] & 0x80) || !!(keystate[DIK_RALT] & 0x80); + k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80) || !!(keystate[DIK_RCONTROL] & 0x80); + k.keycode = i; + receiver(k); + break; + } + } + } + + // keypresses get dropped with high values + Sleep(4); + } +} +#endif \ No newline at end of file -- cgit v1.2.3 From 2d90e4039c6dd1aab00c738f9bbc70a4949cd583 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 06:14:00 +0100 Subject: allow for binding joystick buttons to shortcut functions Win32 only Issue: #118 --- gui/keyboard.h | 16 +- gui/options-dialog.cpp | 44 ++++-- gui/options-dialog.hpp | 2 +- opentrack/keybinding-worker.cpp | 13 ++ opentrack/keybinding-worker.hpp | 5 +- opentrack/shortcuts.cpp | 34 +++-- opentrack/shortcuts.h | 7 +- opentrack/win32-joystick-shortcuts.hpp | 264 +++++++++++++++++++++++++++++++++ 8 files changed, 354 insertions(+), 31 deletions(-) create mode 100644 opentrack/win32-joystick-shortcuts.hpp (limited to 'opentrack/keybinding-worker.cpp') diff --git a/gui/keyboard.h b/gui/keyboard.h index 03edacc7..aa4b4a24 100644 --- a/gui/keyboard.h +++ b/gui/keyboard.h @@ -20,10 +20,17 @@ public: #ifdef _WIN32 , w([&](Key& k) { - Qt::KeyboardModifiers m; - QKeySequence k_; - if (win_key::to_qt(k, k_, m)) - key_pressed(static_cast(k_).toInt() | m); + if(k.guid != "") + { + joystick_button_pressed(k.guid, k.keycode); + } + else + { + Qt::KeyboardModifiers m; + QKeySequence k_; + if (win_key::to_qt(k, k_, m)) + key_pressed(static_cast(k_).toInt() | m); + } }, this->winId()) #endif { @@ -47,4 +54,5 @@ public: #endif signals: void key_pressed(QKeySequence k); + void joystick_button_pressed(QString guid, int idx); }; diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 2778be0f..c8bf668d 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -12,9 +12,18 @@ #include #include +static QString kopts_to_string(const Shortcuts::key_opts& kopts) +{ + if (static_cast(kopts.guid) != "") + return "Joystick button " + QString::number(kopts.button); + if (static_cast(kopts.keycode) == "") + return "None"; + return kopts.keycode; +} + OptionsDialog::OptionsDialog() { - ui.setupUi( this ); + ui.setupUi(this); connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); @@ -53,18 +62,20 @@ OptionsDialog::OptionsDialog() tie_setting(s.s_main.center_method, ui.center_method); - connect(ui.bind_center, &QPushButton::pressed, [&]() -> void { bind_key(s.center.keycode, ui.center_text); }); - connect(ui.bind_zero, &QPushButton::pressed, [&]() -> void { bind_key(s.zero.keycode, ui.zero_text); }); - connect(ui.bind_toggle, &QPushButton::pressed, [&]() -> void { bind_key(s.toggle.keycode, ui.toggle_text); }); + connect(ui.bind_center, &QPushButton::pressed, [&]() -> void { bind_key(s.center, ui.center_text); }); + connect(ui.bind_zero, &QPushButton::pressed, [&]() -> void { bind_key(s.zero, ui.zero_text); }); + connect(ui.bind_toggle, &QPushButton::pressed, [&]() -> void { bind_key(s.toggle, ui.toggle_text); }); - ui.center_text->setText(s.center.keycode == "" ? "None" : static_cast(s.center.keycode)); - ui.toggle_text->setText(s.toggle.keycode == "" ? "None" : static_cast(s.toggle.keycode)); - ui.zero_text->setText(s.zero.keycode == "" ? "None" : static_cast(s.zero.keycode)); + ui.center_text->setText(kopts_to_string(s.center)); + ui.toggle_text->setText(kopts_to_string(s.toggle)); + ui.zero_text->setText(kopts_to_string(s.zero)); } -void OptionsDialog::bind_key(value& ret, QLabel* label) +void OptionsDialog::bind_key(Shortcuts::key_opts& kopts, QLabel* label) { - ret = ""; + kopts.button = -1; + kopts.guid = ""; + kopts.keycode = ""; QDialog d; auto l = new QHBoxLayout; l->setMargin(0); @@ -73,9 +84,20 @@ void OptionsDialog::bind_key(value& ret, QLabel* label) d.setLayout(l); d.setFixedSize(QSize(500, 300)); d.setWindowFlags(Qt::Dialog); - connect(k, &KeyboardListener::key_pressed, [&] (QKeySequence s) -> void { ret = s.toString(QKeySequence::PortableText); d.close(); }); + connect(k, &KeyboardListener::key_pressed, [&] (QKeySequence s) -> void { + kopts.keycode = s.toString(QKeySequence::PortableText); + kopts.guid = ""; + kopts.button = -1; + d.close(); + }); + connect(k, &KeyboardListener::joystick_button_pressed, [&](QString guid, int idx) -> void { + kopts.guid = guid; + kopts.keycode = ""; + kopts.button = idx; + d.close(); + }); d.exec(); - label->setText(ret == "" ? "None" : static_cast(ret)); + label->setText(kopts_to_string(kopts)); delete k; delete l; } diff --git a/gui/options-dialog.hpp b/gui/options-dialog.hpp index 3ef99d06..308b5b0f 100644 --- a/gui/options-dialog.hpp +++ b/gui/options-dialog.hpp @@ -19,5 +19,5 @@ private: private slots: void doOK(); void doCancel(); - void bind_key(value& ret, QLabel* label); + void bind_key(Shortcuts::key_opts &kopts, QLabel* label); }; diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 29b2cf9f..e6c023ef 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -72,6 +72,19 @@ void KeybindingWorker::run() { while (!should_quit) { + { + using joy_fn = std::function; + + joy_fn f = [&](const QString& guid, int idx) -> void { + Key k; + k.keycode = idx; + k.guid = guid; + receiver(k); + }; + + joy_ctx.poll(f); + } + if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) { qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); Sleep(25); diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index e720ffdc..8cf59d65 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -15,6 +15,7 @@ #endif #include "opentrack-compat/timer.hpp" +#include "opentrack/win32-joystick-shortcuts.hpp" #include #include #include @@ -27,6 +28,7 @@ # include struct Key { BYTE keycode; + QString guid; bool shift; bool ctrl; bool alt; @@ -38,7 +40,7 @@ public: bool should_process() { - if (keycode == 0) + if (keycode == 0 && guid == "") return false; bool ret = timer.elapsed_ms() > 100; timer.start(); @@ -56,6 +58,7 @@ private: LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; QMutex mtx; + win32_joy_ctx joy_ctx; public: volatile bool should_quit; std::function receiver; diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp index 5f5ad922..0d7f79b9 100644 --- a/opentrack/shortcuts.cpp +++ b/opentrack/shortcuts.cpp @@ -34,19 +34,27 @@ void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k) key = K(); int idx = 0; QKeySequence code; - - if (k.keycode == "") - code = QKeySequence(Qt::Key_unknown); + + if (k.guid != "") + { + key.guid = k.guid; + key.keycode = k.button; + } else - code = QKeySequence::fromString(k.keycode, QKeySequence::PortableText); - - Qt::KeyboardModifiers mods = Qt::NoModifier; - if (code != Qt::Key_unknown) - win_key::from_qt(code, idx, mods); - key.shift = !!(mods & Qt::ShiftModifier); - key.alt = !!(mods & Qt::AltModifier); - key.ctrl = !!(mods & Qt::ControlModifier); - key.keycode = idx; + { + if (k.keycode == "") + code = QKeySequence(Qt::Key_unknown); + else + code = QKeySequence::fromString(k.keycode, QKeySequence::PortableText); + + Qt::KeyboardModifiers mods = Qt::NoModifier; + if (code != Qt::Key_unknown) + win_key::from_qt(code, idx, mods); + key.shift = !!(mods & Qt::ShiftModifier); + key.alt = !!(mods & Qt::AltModifier); + key.ctrl = !!(mods & Qt::ControlModifier); + key.keycode = idx; + } } #endif @@ -56,6 +64,8 @@ void Shortcuts::receiver(Key &k) std::vector ks { &keyCenter, &keyToggle, &keyZero }; for (K* k_ : ks) { + if (k.guid != k_->guid) + continue; if (k.keycode != k_->keycode) continue; if (!k_->should_process()) diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index 84231850..1643485e 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -47,10 +47,13 @@ public: #endif struct key_opts { - value keycode; + value keycode, guid; + value button; key_opts(pbundle b, const QString& name) : - keycode(b, QString("keycode-%1").arg(name), "") + keycode(b, QString("keycode-%1").arg(name), ""), + guid(b, QString("guid-%1").arg(name), ""), + button(b, QString("button-%1").arg(name), -1) {} }; diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp new file mode 100644 index 00000000..67465bce --- /dev/null +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -0,0 +1,264 @@ +#pragma once + +#include +#include +#include +#include +#include +#ifndef DIRECTINPUT_VERSION +# define DIRECTINPUT_VERSION 0x800 +#endif +#include +#include +#include "opentrack-compat/timer.hpp" +#include +#include + +struct win32_joy_ctx +{ + using fn = std::function; + + void poll(fn f) + { + refresh(); + for (int i = joys.size() - 1; i >= 0; i--) + { + if (!joys[i]->poll(f)) + joys.erase(joys.begin() + i); + } + } + + struct joy + { + LPDIRECTINPUTDEVICE8 joy_handle; + QString guid; + + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid) : joy_handle(handle), guid(guid) + { + qDebug() << "got joy" << guid; + } + + ~joy() + { + qDebug() << "nix joy" << guid; + release(); + } + + void release() + { + if (joy_handle) + { + (void) joy_handle->Unacquire(); + joy_handle->Release(); + joy_handle = nullptr; + } + } + + bool poll(fn f) + { + HRESULT hr; + bool ok = false; + + for (int i = 0; i < 5; i++) + { + if (!FAILED(joy_handle->Poll())) + { + ok = true; + break; + } + if ((hr = joy_handle->Acquire()) != DI_OK) + continue; + else + ok = true; + break; + } + + if (!ok) + { + qDebug() << "joy acquire failed" << guid << hr; + return false; + } + + DIJOYSTATE2 js; + + if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) + { + qDebug() << "joy get state failed" << guid << hr; + return false; + } + + for (int i = 0; i < 128; i++) + if (js.rgbButtons[i] & 0x80) + f(guid, i); + + return true; + } + }; + + static QString guid_to_string(const GUID guid) + { + char buf[40] = {0}; + wchar_t szGuidW[40] = {0}; + + StringFromGUID2(guid, szGuidW, 40); + WideCharToMultiByte(0, 0, szGuidW, -1, buf, 40, NULL, NULL); + + return QString(buf); + } + + win32_joy_ctx() : dinput_handle(nullptr) + { + (void) CoInitialize(nullptr); + + HRESULT hr; + + if (FAILED(hr = DirectInput8Create(GetModuleHandle(nullptr), + DIRECTINPUT_VERSION, + IID_IDirectInput8, + (void**) &dinput_handle, + nullptr))) + goto fail; + + return; +fail: + qDebug() << "dinput8 failed for shortcuts" << hr; + + release(); + } + + ~win32_joy_ctx() + { + release(); + } + + void release() + { + joys = std::vector>(); + if (dinput_handle) + { + dinput_handle->Release(); + dinput_handle = nullptr; + } + } + + void refresh() + { + if (!dinput_handle) + return; + + if (timer_joylist.elapsed_ms() < joylist_refresh_ms) + return; + + timer_joylist.start(); + + enum_state st(dinput_handle, joys); + } + + struct enum_state + { + std::vector>& joys; + std::vector all; + LPDIRECTINPUT8 dinput_handle; + + enum_state(LPDIRECTINPUT8 di, std::vector>& joys) : joys(joys), dinput_handle(di) + { + HRESULT hr; + + if(FAILED(hr = dinput_handle->EnumDevices(DI8DEVCLASS_GAMECTRL, + EnumJoysticksCallback, + this, + DIEDFL_ATTACHEDONLY))) + { + qDebug() << "failed enum joysticks" << hr; + return; + } + + for (int i = joys.size() - 1; i >= 0; i--) + { + const auto& guid = joys[i]->guid; + if (std::find_if(all.cbegin(), all.cend(), [&](const QString& guid2) -> bool { return guid == guid2; }) == all.cend()) + joys.erase(joys.begin() + i); + } + } + + static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext) + { + enum_state& state = *reinterpret_cast(pContext); + const QString guid = guid_to_string(pdidInstance->guidInstance); +#if 0 + const QString name = QString(pdidInstance->tszInstanceName); + // the logic here is that iff multiple joysticks of same name exist, then take guids into account at all + const int cnt_names = std::count_if(state.joys.begin(), state.joys.end(), [&](const joy& j) -> bool { return j.name == name; }); + // this is potentially bad since replugged sticks can change guids (?) +#endif + + const bool exists = std::find_if(state.joys.cbegin(), + state.joys.cend(), + [&](const std::shared_ptr& j) -> bool { return j->guid == guid; }) != state.joys.cend(); + + state.all.push_back(guid); + + if (!exists) + { + HRESULT hr; + LPDIRECTINPUTDEVICE8 h; + if (FAILED(hr = state.dinput_handle->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) + { + qDebug() << "create joystick breakage" << guid << hr; + goto end; + } + if (FAILED(h->SetDataFormat(&c_dfDIJoystick2))) + { + qDebug() << "format"; + h->Release(); + goto end; + } + + if (FAILED(h->SetCooperativeLevel((HWND) GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) + { + qDebug() << "coop"; + h->Release(); + goto end; + } +#if 0 + if (FAILED(hr = h->EnumObjects(EnumObjectsCallback, h, DIDFT_ALL))) + { + qDebug() << "enum-objects"; + h->Release(); + goto end; + } +#endif + state.joys.push_back(std::make_shared(h, guid)); + } + +end: return DIENUM_CONTINUE; + } + +#if 0 + static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx) + { + if (pdidoi->dwType & DIDFT_AXIS) + { + DIPROPRANGE diprg; + memset(&diprg, 0, sizeof(diprg)); + diprg.diph.dwSize = sizeof( DIPROPRANGE ); + diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER ); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = pdidoi->dwType; + diprg.lMax = 32; + diprg.lMin = -32; + + if (FAILED(reinterpret_cast(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph))) + return DIENUM_STOP; + } + + return DIENUM_CONTINUE; + } +#endif + }; + + LPDIRECTINPUT8 dinput_handle; + std::vector> joys; + Timer timer_joylist; + enum { joylist_refresh_ms = 2000 }; +}; \ No newline at end of file -- cgit v1.2.3 From 17849b12f232c89bdae16f7e179d3a92a32280ad Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 13:44:45 +0100 Subject: shortcuts: map joystick buttons on depress only Some buttons like the X65 mode switch are held all the time. Prevent them from hogging all the keybindings. Issue: #118 --- gui/keyboard.h | 4 ++-- gui/options-dialog.cpp | 13 ++++++++----- opentrack/keybinding-worker.cpp | 5 +++-- opentrack/keybinding-worker.hpp | 3 ++- opentrack/win32-joystick-shortcuts.hpp | 13 ++++++++++--- 5 files changed, 25 insertions(+), 13 deletions(-) (limited to 'opentrack/keybinding-worker.cpp') diff --git a/gui/keyboard.h b/gui/keyboard.h index aa4b4a24..b840bc78 100644 --- a/gui/keyboard.h +++ b/gui/keyboard.h @@ -22,7 +22,7 @@ public: { if(k.guid != "") { - joystick_button_pressed(k.guid, k.keycode); + joystick_button_pressed(k.guid, k.keycode, k.held); } else { @@ -54,5 +54,5 @@ public: #endif signals: void key_pressed(QKeySequence k); - void joystick_button_pressed(QString guid, int idx); + void joystick_button_pressed(QString guid, int idx, bool held); }; diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index c8bf668d..4cff6e77 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -90,11 +90,14 @@ void OptionsDialog::bind_key(Shortcuts::key_opts& kopts, QLabel* label) kopts.button = -1; d.close(); }); - connect(k, &KeyboardListener::joystick_button_pressed, [&](QString guid, int idx) -> void { - kopts.guid = guid; - kopts.keycode = ""; - kopts.button = idx; - d.close(); + connect(k, &KeyboardListener::joystick_button_pressed, [&](QString guid, int idx, bool held) -> void { + if (!held) + { + kopts.guid = guid; + kopts.keycode = ""; + kopts.button = idx; + d.close(); + } }); d.exec(); label->setText(kopts_to_string(kopts)); diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index e6c023ef..e9255801 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -73,12 +73,13 @@ void KeybindingWorker::run() { while (!should_quit) { { - using joy_fn = std::function; + using joy_fn = std::function; - joy_fn f = [&](const QString& guid, int idx) -> void { + joy_fn f = [&](const QString& guid, int idx, bool held) -> void { Key k; k.keycode = idx; k.guid = guid; + k.held = held; receiver(k); }; diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 8cf59d65..cb3e5f9f 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -32,9 +32,10 @@ struct Key { bool shift; bool ctrl; bool alt; + bool held; Timer timer; public: - Key() : keycode(0), shift(false), ctrl(false), alt(false) + Key() : keycode(0), shift(false), ctrl(false), alt(false), held(true) { } diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp index 67465bce..3c839197 100644 --- a/opentrack/win32-joystick-shortcuts.hpp +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -16,7 +16,7 @@ struct win32_joy_ctx { - using fn = std::function; + using fn = std::function; void poll(fn f) { @@ -32,10 +32,13 @@ struct win32_joy_ctx { LPDIRECTINPUTDEVICE8 joy_handle; QString guid; + bool pressed[128]; joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid) : joy_handle(handle), guid(guid) { qDebug() << "got joy" << guid; + for (int i = 0; i < 128; i++) + pressed[i] = false; } ~joy() @@ -88,8 +91,12 @@ struct win32_joy_ctx } for (int i = 0; i < 128; i++) - if (js.rgbButtons[i] & 0x80) - f(guid, i); + { + const bool state = !!(js.rgbButtons[i] & 0x80); + if (state != pressed[i]) + f(guid, i, state); + pressed[i] = state; + } return true; } -- cgit v1.2.3 From c8805112acca1ba3bd0056fcf0b9332c4ba10f03 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 15:28:50 +0100 Subject: shortcuts: alloy kbd mods for joystick buttons --- gui/keyboard.h | 6 +++++- opentrack/keybinding-worker.cpp | 21 ++++++++++++++------- opentrack/shortcuts.cpp | 5 ++++- 3 files changed, 23 insertions(+), 9 deletions(-) (limited to 'opentrack/keybinding-worker.cpp') diff --git a/gui/keyboard.h b/gui/keyboard.h index b840bc78..75226aa3 100644 --- a/gui/keyboard.h +++ b/gui/keyboard.h @@ -22,7 +22,11 @@ public: { if(k.guid != "") { - joystick_button_pressed(k.guid, k.keycode, k.held); + int mods = 0; + if (k.alt) mods |= Qt::AltModifier; + if (k.shift) mods |= Qt::ShiftModifier; + if (k.ctrl) mods |= Qt::ControlModifier; + joystick_button_pressed(k.guid, k.keycode | mods, k.held); } else { diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index e9255801..fd777211 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -68,16 +68,29 @@ KeybindingWorker::KeybindingWorker(std::function receiver, WId h) : } void KeybindingWorker::run() { - BYTE keystate[256]; + BYTE keystate[256] = {0}; while (!should_quit) { + { + const HRESULT hr = dinkeyboard->GetDeviceState(256, (LPVOID)keystate); + + if (hr != DI_OK) { + qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); + Sleep(25); + continue; + } + } + { using joy_fn = std::function; joy_fn f = [&](const QString& guid, int idx, bool held) -> void { Key k; k.keycode = idx; + k.shift = !!(keystate[DIK_LSHIFT] & 0x80 || keystate[DIK_RSHIFT] & 0x80); + k.alt = !!(keystate[DIK_LALT] & 0x80 || keystate[DIK_RALT] & 0x80); + k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80 || keystate[DIK_RCONTROL] & 0x80); k.guid = guid; k.held = held; receiver(k); @@ -85,12 +98,6 @@ void KeybindingWorker::run() { joy_ctx.poll(f); } - - if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) { - qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); - Sleep(25); - continue; - } QMutexLocker l(&mtx); diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp index 108b6b3b..6eab6071 100644 --- a/opentrack/shortcuts.cpp +++ b/opentrack/shortcuts.cpp @@ -38,7 +38,10 @@ void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k) if (k.guid != "") { key.guid = k.guid; - key.keycode = k.button; + key.keycode = k.button & ~Qt::KeyboardModifierMask; + key.ctrl = !!(k.button & Qt::ControlModifier); + key.alt = !!(k.button & Qt::AltModifier); + key.shift = !!(k.button & Qt::ShiftModifier); } else { -- cgit v1.2.3 From 42217bbb858ddb158ad13777e2aace942aaf9525 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 19 Nov 2015 01:41:49 +0100 Subject: shortcuts: nix single-use mutex It also slept with lock held. Good riddance. --- opentrack/keybinding-worker.cpp | 2 -- opentrack/keybinding-worker.hpp | 1 - opentrack/shortcuts.cpp | 1 - 3 files changed, 4 deletions(-) (limited to 'opentrack/keybinding-worker.cpp') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index fd777211..31eb9e80 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -99,8 +99,6 @@ void KeybindingWorker::run() { joy_ctx.poll(f); } - QMutexLocker l(&mtx); - for (int i = 0; i < 256; i++) { Key k; diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index cb3e5f9f..b5d63fac 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -58,7 +58,6 @@ struct OPENTRACK_EXPORT KeybindingWorker : public QThread { private: LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; - QMutex mtx; win32_joy_ctx joy_ctx; public: volatile bool should_quit; diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp index 6eab6071..059febdb 100644 --- a/opentrack/shortcuts.cpp +++ b/opentrack/shortcuts.cpp @@ -8,7 +8,6 @@ #include "shortcuts.h" #include "win32-shortcuts.h" -#include void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k) { -- cgit v1.2.3 From a9860e951757bf454b83b13ce7eff865f0b6644e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 15:06:30 +0100 Subject: api/keyboard: implement a central worker DirectInput dies when two LPDIRECTINPUT8 handles are obtained. Implement a singleton worker providing keypress events. --- opentrack/keybinding-worker.cpp | 153 ++++++++++++++++++++++++++-------------- opentrack/keybinding-worker.hpp | 48 ++++++++++--- 2 files changed, 137 insertions(+), 64 deletions(-) (limited to 'opentrack/keybinding-worker.cpp') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 31eb9e80..d876d5a1 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -9,11 +9,14 @@ #include "keybinding-worker.hpp" #if defined(_WIN32) -# include -# include -# include + +#include +#include +#include +#include KeybindingWorker::~KeybindingWorker() { + qDebug() << "keybinding worker stop"; should_quit = true; wait(); if (dinkeyboard) { @@ -24,11 +27,8 @@ KeybindingWorker::~KeybindingWorker() { din->Release(); } -KeybindingWorker::KeybindingWorker(std::function receiver, WId h) : - should_quit(true), receiver(receiver) +KeybindingWorker::KeybindingWorker() : should_quit(true) { - HWND handle = reinterpret_cast(h); - if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); return; @@ -47,7 +47,7 @@ KeybindingWorker::KeybindingWorker(std::function receiver, WId h) : din = 0; return; } - if (dinkeyboard->SetCooperativeLevel((HWND) handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { + if (dinkeyboard->SetCooperativeLevel(GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { dinkeyboard->Release(); din->Release(); din = 0; @@ -65,6 +65,13 @@ KeybindingWorker::KeybindingWorker(std::function receiver, WId h) : return; } should_quit = false; + start(); +} + +KeybindingWorker& KeybindingWorker::make() +{ + static KeybindingWorker k; + return k; } void KeybindingWorker::run() { @@ -73,59 +80,99 @@ void KeybindingWorker::run() { while (!should_quit) { { - const HRESULT hr = dinkeyboard->GetDeviceState(256, (LPVOID)keystate); - - if (hr != DI_OK) { - qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); - Sleep(25); - continue; - } - } - - { - using joy_fn = std::function; - - joy_fn f = [&](const QString& guid, int idx, bool held) -> void { - Key k; - k.keycode = idx; - k.shift = !!(keystate[DIK_LSHIFT] & 0x80 || keystate[DIK_RSHIFT] & 0x80); - k.alt = !!(keystate[DIK_LALT] & 0x80 || keystate[DIK_RALT] & 0x80); - k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80 || keystate[DIK_RCONTROL] & 0x80); - k.guid = guid; - k.held = held; - receiver(k); - }; + QMutexLocker l(&mtx); - joy_ctx.poll(f); - } - - for (int i = 0; i < 256; i++) - { - Key k; - if (keystate[i] & 0x80) + if (receivers.size()) { - switch (i) { - case DIK_LCONTROL: - case DIK_LSHIFT: - case DIK_LALT: - case DIK_RCONTROL: - case DIK_RSHIFT: - case DIK_RALT: - break; - default: - k.shift = !!(keystate[DIK_LSHIFT] & 0x80) || !!(keystate[DIK_RSHIFT] & 0x80); - k.alt = !!(keystate[DIK_LALT] & 0x80) || !!(keystate[DIK_RALT] & 0x80); - k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80) || !!(keystate[DIK_RCONTROL] & 0x80); - k.keycode = i; - receiver(k); - break; + const HRESULT hr = dinkeyboard->GetDeviceState(256, (LPVOID)keystate); + + if (hr != DI_OK) { + qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); + Sleep(25); + continue; + } + } + + { + using joy_fn = std::function; + + joy_fn f = [&](const QString& guid, int idx, bool held) -> void { + Key k; + k.keycode = idx; + k.shift = !!(keystate[DIK_LSHIFT] & 0x80 || keystate[DIK_RSHIFT] & 0x80); + k.alt = !!(keystate[DIK_LALT] & 0x80 || keystate[DIK_RALT] & 0x80); + k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80 || keystate[DIK_RCONTROL] & 0x80); + k.guid = guid; + k.held = held; + + for (auto& r : receivers) + r(k); + }; + + joy_ctx.poll(f); + } + + for (int i = 0; i < 256; i++) + { + Key k; + if (keystate[i] & 0x80) + { + switch (i) + { + case DIK_LCONTROL: + case DIK_LSHIFT: + case DIK_LALT: + case DIK_RCONTROL: + case DIK_RSHIFT: + case DIK_RALT: + break; + default: + k.shift = !!(keystate[DIK_LSHIFT] & 0x80) || !!(keystate[DIK_RSHIFT] & 0x80); + k.alt = !!(keystate[DIK_LALT] & 0x80) || !!(keystate[DIK_RALT] & 0x80); + k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80) || !!(keystate[DIK_RCONTROL] & 0x80); + k.keycode = i; + + for (auto& r : receivers) + r(k); + break; + } + } } } } - + // keypresses get dropped with high values Sleep(4); } } + +KeybindingWorker::fun* KeybindingWorker::_add_receiver(KeybindingWorker::fun receiver) +{ + QMutexLocker l(&mtx); + receivers.push_back(receiver); + qDebug() << "add receiver" << (long) &receivers[receivers.size()-1]; + return &receivers[receivers.size()-1]; +} + +void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) +{ + QMutexLocker l(&mtx); + bool ok = false; + + for (int i = receivers.size() - 1; i >= 0; i--) + { + if (&receivers[i] == pos) + { + ok = true; + qDebug() << "remove receiver" << (long) pos; + receivers.erase(receivers.begin() + i); + } + } + if (!ok) + { + qDebug() << "bad remove receiver" << (long) pos; + } +} + #endif \ No newline at end of file diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index b5d63fac..5a73b1b1 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #ifdef _WIN32 # undef DIRECTINPUT_VERSION @@ -53,21 +54,46 @@ typedef unsigned char BYTE; struct Key { int foo; }; #endif -struct OPENTRACK_EXPORT KeybindingWorker : public QThread { -#ifdef _WIN32 +struct OPENTRACK_EXPORT KeybindingWorker : private QThread +{ private: LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; win32_joy_ctx joy_ctx; -public: volatile bool should_quit; - std::function receiver; + using fun = std::function; + std::vector receivers; + QMutex mtx; + + void run() override; + KeybindingWorker(); + + KeybindingWorker(const KeybindingWorker&) = delete; + KeybindingWorker& operator=(KeybindingWorker&) = delete; + static KeybindingWorker& make(); + fun* _add_receiver(fun receiver); + void remove_receiver(fun* pos); ~KeybindingWorker(); - KeybindingWorker(std::function receiver, WId h); - void run(); -#else public: - KeybindingWorker(Key, Key, Key, WId) {} - void run() {} -#endif -}; \ No newline at end of file + class Token + { + friend class KeybindingWorker; + fun* pos; + //Token(const Token&) = delete; + Token& operator=(Token&) = delete; + public: + Token(fun receiver) + { + pos = make()._add_receiver(receiver); + } + ~Token() + { + make().remove_receiver(pos); + } + }; + friend class Token; + static Token add_receiver(fun receiver) + { + return Token(receiver); + } +}; -- cgit v1.2.3 From 119671e4e7f4dc07c1fb20eb999a0a7fcfbbdba8 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 15:50:46 +0100 Subject: api/shortcuts, tracker/joy: adapt to synchronized joy api --- opentrack/keybinding-worker.cpp | 2 +- opentrack/keybinding-worker.hpp | 2 +- tracker-joystick/ftnoir_tracker_joystick.cpp | 11 ++++++++++- tracker-joystick/ftnoir_tracker_joystick.h | 2 +- tracker-joystick/ftnoir_tracker_joystick_dialog.cpp | 9 +++++---- 5 files changed, 18 insertions(+), 8 deletions(-) (limited to 'opentrack/keybinding-worker.cpp') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index d876d5a1..5f42f44e 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -27,7 +27,7 @@ KeybindingWorker::~KeybindingWorker() { din->Release(); } -KeybindingWorker::KeybindingWorker() : should_quit(true) +KeybindingWorker::KeybindingWorker() : joy_ctx(win32_joy_ctx::make()), should_quit(true) { if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 5a73b1b1..551be144 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -59,7 +59,7 @@ struct OPENTRACK_EXPORT KeybindingWorker : private QThread private: LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; - win32_joy_ctx joy_ctx; + win32_joy_ctx& joy_ctx; volatile bool should_quit; using fun = std::function; std::vector receivers; diff --git a/tracker-joystick/ftnoir_tracker_joystick.cpp b/tracker-joystick/ftnoir_tracker_joystick.cpp index 4c180eaa..112f20ca 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick.cpp @@ -8,8 +8,17 @@ #include "opentrack/plugin-api.hpp" #include -FTNoIR_Tracker::FTNoIR_Tracker() +FTNoIR_Tracker::FTNoIR_Tracker() : joy_ctx(win32_joy_ctx::make()) { + if (static_cast(s.guid) == "") + { + std::vector info = joy_ctx.get_joy_info(); + if (info.size()) + { + s.guid = info[0].guid; + s.b->save(); + } + } } FTNoIR_Tracker::~FTNoIR_Tracker() diff --git a/tracker-joystick/ftnoir_tracker_joystick.h b/tracker-joystick/ftnoir_tracker_joystick.h index 18ac349e..e94e2ee7 100644 --- a/tracker-joystick/ftnoir_tracker_joystick.h +++ b/tracker-joystick/ftnoir_tracker_joystick.h @@ -47,7 +47,7 @@ public: settings s; QString guid; static constexpr int AXIS_MAX = win32_joy_ctx::joy_axis_size - 1; - win32_joy_ctx joy_ctx; + win32_joy_ctx& joy_ctx; }; class TrackerControls: public ITrackerDialog diff --git a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp index 28846809..1ca1441c 100644 --- a/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp +++ b/tracker-joystick/ftnoir_tracker_joystick_dialog.cpp @@ -10,20 +10,21 @@ TrackerControls::TrackerControls() : tracker(nullptr) connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); { - win32_joy_ctx joy_ctx; + win32_joy_ctx& joy_ctx(win32_joy_ctx::make()); _joys = QList(); - for (auto& j : joy_ctx.joys()) - _joys.push_back(joys { j.second->name, j.first }); + for (auto j : joy_ctx.get_joy_info()) + _joys.push_back(joys { j.name, j.guid }); } { + const QString guid = s.guid; int idx = 0; for (int i = 0; i < _joys.size(); i++) { const joys& j = _joys[i]; - if (j.guid == s.guid && j.name == s.joyid) + if (j.guid == guid) idx = i; ui.joylist->addItem(j.name + " " + j.guid); } -- cgit v1.2.3 From 0c3a306b8588ae1cbe190ee18db2336bcd0eb527 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 17:46:46 +0100 Subject: api/shortcuts: hopefully guard joystick _WIN32 --- opentrack/keybinding-worker.cpp | 8 +++++++- opentrack/keybinding-worker.hpp | 6 +++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'opentrack/keybinding-worker.cpp') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 5f42f44e..3659a768 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -27,7 +27,11 @@ KeybindingWorker::~KeybindingWorker() { din->Release(); } -KeybindingWorker::KeybindingWorker() : joy_ctx(win32_joy_ctx::make()), should_quit(true) +KeybindingWorker::KeybindingWorker() : +#ifdef _WIN32 + joy_ctx(win32_joy_ctx::make()), +#endif + should_quit(true) { if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); @@ -94,6 +98,7 @@ void KeybindingWorker::run() { } } +#ifdef _WIN32 { using joy_fn = std::function; @@ -112,6 +117,7 @@ void KeybindingWorker::run() { joy_ctx.poll(f); } +#endif for (int i = 0; i < 256; i++) { diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 8474ae1e..c4a39ec6 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -15,7 +15,9 @@ #endif #include "opentrack-compat/timer.hpp" -#include "opentrack/win32-joystick.hpp" +#ifdef _WIN32 +# include "opentrack/win32-joystick.hpp" +#endif #include #include #include @@ -59,7 +61,9 @@ struct OPENTRACK_EXPORT KeybindingWorker : private QThread private: LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; +#ifdef _WIN32 win32_joy_ctx& joy_ctx; +#endif volatile bool should_quit; using fun = std::function; std::vector receivers; -- cgit v1.2.3 From e2ea45a81d5f30fdbd42e0b03a192afa81e877dc Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 22 Nov 2015 18:05:04 +0100 Subject: api/shortcuts: don't provide guard/stubs for non-win32 The worker class is win32-only. Don't guard there, consumers are expected only to include it on _WIN32. For the same reason don't provide a stub for the keybinding worker. --- opentrack/keybinding-worker.cpp | 29 ++++++++++++++--------------- opentrack/keybinding-worker.hpp | 20 +++++--------------- 2 files changed, 19 insertions(+), 30 deletions(-) (limited to 'opentrack/keybinding-worker.cpp') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 3659a768..dcf5c1b6 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -6,10 +6,9 @@ * notice appear in all copies. */ -#include "keybinding-worker.hpp" - -#if defined(_WIN32) +#ifdef _WIN32 +#include "keybinding-worker.hpp" #include #include #include @@ -29,7 +28,7 @@ KeybindingWorker::~KeybindingWorker() { KeybindingWorker::KeybindingWorker() : #ifdef _WIN32 - joy_ctx(win32_joy_ctx::make()), + joy_ctx(win32_joy_ctx::make()), #endif should_quit(true) { @@ -85,23 +84,23 @@ void KeybindingWorker::run() { { { QMutexLocker l(&mtx); - + if (receivers.size()) { { const HRESULT hr = dinkeyboard->GetDeviceState(256, (LPVOID)keystate); - + if (hr != DI_OK) { qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); Sleep(25); continue; } } - + #ifdef _WIN32 { using joy_fn = std::function; - + joy_fn f = [&](const QString& guid, int idx, bool held) -> void { Key k; k.keycode = idx; @@ -110,15 +109,15 @@ void KeybindingWorker::run() { k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80 || keystate[DIK_RCONTROL] & 0x80); k.guid = guid; k.held = held; - + for (auto& r : receivers) r(k); }; - + joy_ctx.poll(f); } #endif - + for (int i = 0; i < 256; i++) { Key k; @@ -138,7 +137,7 @@ void KeybindingWorker::run() { k.alt = !!(keystate[DIK_LALT] & 0x80) || !!(keystate[DIK_RALT] & 0x80); k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80) || !!(keystate[DIK_RCONTROL] & 0x80); k.keycode = i; - + for (auto& r : receivers) r(k); break; @@ -147,7 +146,7 @@ void KeybindingWorker::run() { } } } - + // keypresses get dropped with high values Sleep(4); } @@ -165,7 +164,7 @@ void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) { QMutexLocker l(&mtx); bool ok = false; - + for (int i = receivers.size() - 1; i >= 0; i--) { if (&receivers[i] == pos) @@ -181,4 +180,4 @@ void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) } } -#endif \ No newline at end of file +#endif diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 83ffadf1..e3967682 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -15,20 +15,17 @@ #endif #include "opentrack-compat/timer.hpp" -#ifdef _WIN32 -# include "opentrack/win32-joystick.hpp" -#endif +#include "opentrack/win32-joystick.hpp" #include #include #include #include #include -#ifdef _WIN32 -# undef DIRECTINPUT_VERSION -# define DIRECTINPUT_VERSION 0x0800 -# include -# include +#undef DIRECTINPUT_VERSION +#define DIRECTINPUT_VERSION 0x0800 +#include +#include struct Key { BYTE keycode; QString guid; @@ -51,15 +48,10 @@ public: return ret; } }; -#else -typedef unsigned char BYTE; -struct Key { int foo; }; -#endif struct OPENTRACK_EXPORT KeybindingWorker : private QThread { private: -#ifdef _WIN32 LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; win32_joy_ctx& joy_ctx; @@ -99,7 +91,5 @@ public: { return Token(receiver); } -#else void run() override {} -#endif }; -- cgit v1.2.3 From 3566dc23946b798b396946297cbf70f2d46fd242 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 26 Nov 2015 09:04:29 +0100 Subject: api/shortcuts: move to separate definition There's no need to have definitions in header for non-template classes --- opentrack/keybinding-worker.cpp | 10 ++ opentrack/keybinding-worker.hpp | 13 +- opentrack/win32-joystick.cpp | 275 +++++++++++++++++++++++++++++++++++ opentrack/win32-joystick.hpp | 308 ++++------------------------------------ 4 files changed, 315 insertions(+), 291 deletions(-) (limited to 'opentrack/keybinding-worker.cpp') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index dcf5c1b6..59bc4afd 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -14,6 +14,15 @@ #include #include +bool Key::should_process() +{ + if (keycode == 0 && guid == "") + return false; + bool ret = timer.elapsed_ms() > 100; + timer.start(); + return ret; +} + KeybindingWorker::~KeybindingWorker() { qDebug() << "keybinding worker stop"; should_quit = true; @@ -172,6 +181,7 @@ void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) ok = true; qDebug() << "remove receiver" << (long) pos; receivers.erase(receivers.begin() + i); + break; } } if (!ok) diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 7661f88d..054182e7 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -35,18 +35,9 @@ struct Key { bool held; Timer timer; public: - Key() : keycode(0), shift(false), ctrl(false), alt(false), held(true) - { - } + Key() : keycode(0), shift(false), ctrl(false), alt(false), held(true) {} - bool should_process() - { - if (keycode == 0 && guid == "") - return false; - bool ret = timer.elapsed_ms() > 100; - timer.start(); - return ret; - } + bool should_process(); }; struct OPENTRACK_EXPORT KeybindingWorker : private QThread diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 56a1b070..29a51a43 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -31,4 +31,279 @@ win32_joy_ctx& win32_joy_ctx::make() return ret; } +void win32_joy_ctx::poll(fn f) +{ + QMutexLocker l(&mtx); + + refresh(false); + for (auto& j : joys()) + { + j.second->poll(f); + } +} + +bool win32_joy_ctx::poll_axis(const QString &guid, int axes[]) +{ + QMutexLocker l(&mtx); + + refresh(false); + + auto iter = joys().find(guid); + + if (iter == joys().end() || iter->second->joy_handle == nullptr) + return false; + + auto& j = iter->second; + + auto& joy_handle = j->joy_handle; + bool ok = false; + HRESULT hr; + + (void) joy_handle->Acquire(); + + if (!FAILED(hr = joy_handle->Poll())) + ok = true; + + if (!ok) + { + qDebug() << "joy acquire failed" << guid << hr; + (void) joy_handle->Unacquire(); + return false; + } + + DIJOYSTATE2 js; + memset(&js, 0, sizeof(js)); + + if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) + { + qDebug() << "joy get state failed" << guid << hr; + return false; + } + + const int values[] = { + js.lX, + js.lY, + js.lZ, + js.lRx, + js.lRy, + js.lRz, + js.rglSlider[0], + js.rglSlider[1] + }; + + for (int i = 0; i < 8; i++) + axes[i] = values[i]; + + return true; +} + +win32_joy_ctx::~win32_joy_ctx() +{ + release(); +} + +std::vector win32_joy_ctx::get_joy_info() +{ + QMutexLocker l(&mtx); + + std::vector ret; + + for (auto& j : joys()) + ret.push_back(joy_info { j.second->name, j.first }); + + return ret; +} + +win32_joy_ctx::win32_joy_ctx() +{ + refresh(true); +} + +void win32_joy_ctx::release() +{ + qDebug() << "release joystick dinput handle"; + joys() = std::unordered_map>(); + { + auto& di = dinput_handle(); + di->Release(); + di = nullptr; + } +} + +void win32_joy_ctx::refresh(bool first) +{ + if (!first) + { + if (timer_joylist.elapsed_ms() < joylist_refresh_ms) + return; + timer_joylist.start(); + } + + enum_state st(joys(), first); +} + +QString win32_joy_ctx::guid_to_string(const GUID guid) +{ + char buf[40] = {0}; + wchar_t szGuidW[40] = {0}; + + StringFromGUID2(guid, szGuidW, 40); + WideCharToMultiByte(0, 0, szGuidW, -1, buf, 40, NULL, NULL); + + return QString(buf); +} + +using fn = win32_joy_ctx::fn; + +void win32_joy_ctx::joy::release() +{ + if (joy_handle) + { + (void) joy_handle->Unacquire(); + joy_handle->Release(); + joy_handle = nullptr; + } +} + +bool win32_joy_ctx::joy::poll(fn f) +{ + HRESULT hr; + bool ok = false; + + if (joy_handle == nullptr) + return false; + + (void) joy_handle->Acquire(); + + if (!FAILED(joy_handle->Poll())) + ok = true; + + if (!ok) + { + qDebug() << "joy acquire failed" << guid << hr; + (void) joy_handle->Unacquire(); + return false; + } + + DIJOYSTATE2 js; + memset(&js, 0, sizeof(js)); + + if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) + { + qDebug() << "joy get state failed" << guid << hr; + return false; + } + + first |= first_timer.elapsed_ms() > first_event_delay_ms; + + for (int i = 0; i < 128; i++) + { + const bool state = !!(js.rgbButtons[i] & 0x80); + if (state != pressed[i] && first) + { + f(guid, i, state); + qDebug() << "btn" << guid << i << state; + } + pressed[i] = state; + } + + return true; +} + +win32_joy_ctx::enum_state::enum_state(std::unordered_map > &joys, bool first) : joys(joys), first(first) +{ + HRESULT hr; + LPDIRECTINPUT8 di = dinput_handle(); + + if(FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, + EnumJoysticksCallback, + this, + DIEDFL_ATTACHEDONLY))) + { + qDebug() << "failed enum joysticks" << hr; + return; + } + + for (auto it = joys.begin(); it != joys.end(); ) + { + if (std::find_if(all.cbegin(), all.cend(), [&](const QString& guid2) -> bool { return it->second->guid == guid2; }) == all.cend()) + it = joys.erase(it); + else + it++; + } +} + +win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidInstance, void *pContext) +{ + enum_state& state = *reinterpret_cast(pContext); + const QString guid = guid_to_string(pdidInstance->guidInstance); + const QString name = QString(pdidInstance->tszInstanceName); + + auto it = state.joys.find(guid); + const bool exists = it != state.joys.end() && it->second->joy_handle != nullptr; + + state.all.push_back(guid); + + if (!exists) + { + HRESULT hr; + LPDIRECTINPUTDEVICE8 h; + LPDIRECTINPUT8 di = dinput_handle(); + if (FAILED(hr = di->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) + { + qDebug() << "createdevice" << guid << hr; + goto end; + } + if (FAILED(h->SetDataFormat(&c_dfDIJoystick2))) + { + qDebug() << "format"; + h->Release(); + goto end; + } + + if (FAILED(h->SetCooperativeLevel((HWND) GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) + { + qDebug() << "coop"; + h->Release(); + goto end; + } + if (FAILED(hr = h->EnumObjects(EnumObjectsCallback, h, DIDFT_ALL))) + { + qDebug() << "enum-objects"; + h->Release(); + goto end; + } + + qDebug() << "add joy" << guid; + state.joys[guid] = std::make_shared(h, guid, name, state.first); + } +end: + return DIENUM_CONTINUE; +} + +win32_joy_ctx::enum_state::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE *pdidoi, void *ctx) +{ + if (pdidoi->dwType & DIDFT_AXIS) + { + DIPROPRANGE diprg; + memset(&diprg, 0, sizeof(diprg)); + diprg.diph.dwSize = sizeof( DIPROPRANGE ); + diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER ); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = pdidoi->dwType; + diprg.lMax = joy_axis_size; + diprg.lMin = -joy_axis_size; + + HRESULT hr; + + if (FAILED(hr = reinterpret_cast(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph))) + { + qDebug() << "DIPROP_RANGE" << hr; + return DIENUM_STOP; + } + } + + return DIENUM_CONTINUE; +} + #endif diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index b08da6c8..334b617a 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -39,77 +39,6 @@ struct hash struct OPENTRACK_EXPORT win32_joy_ctx { using fn = std::function; - - void poll(fn f) - { - QMutexLocker l(&mtx); - - refresh(false); - for (auto& j : joys()) - { - j.second->poll(f); - } - } - - bool poll_axis(const QString& guid, int axes[8]) - { - QMutexLocker l(&mtx); - - refresh(false); - - auto iter = joys().find(guid); - - if (iter == joys().end() || iter->second->joy_handle == nullptr) - return false; - - auto& j = iter->second; - - auto& joy_handle = j->joy_handle; - bool ok = false; - HRESULT hr; - - (void) joy_handle->Acquire(); - - if (!FAILED(hr = joy_handle->Poll())) - ok = true; - - if (!ok) - { - qDebug() << "joy acquire failed" << guid << hr; - (void) joy_handle->Unacquire(); - return false; - } - - DIJOYSTATE2 js; - memset(&js, 0, sizeof(js)); - - if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) - { - qDebug() << "joy get state failed" << guid << hr; - return false; - } - - const int values[] = { - js.lX, - js.lY, - js.lZ, - js.lRx, - js.lRy, - js.lRz, - js.rglSlider[0], - js.rglSlider[1] - }; - - for (int i = 0; i < 8; i++) - axes[i] = values[i]; - - return true; - } - - ~win32_joy_ctx() - { - release(); - } enum { joy_axis_size = 65535 }; @@ -117,78 +46,42 @@ struct OPENTRACK_EXPORT win32_joy_ctx { QString name, guid; }; - - std::vector get_joy_info() - { - QMutexLocker l(&mtx); - - std::vector ret; - - for (auto& j : joys()) - ret.push_back(joy_info { j.second->name, j.first }); - - return ret; - } + void poll(fn f); + bool poll_axis(const QString& guid, int axes[8]); + ~win32_joy_ctx(); + std::vector get_joy_info(); static win32_joy_ctx& make(); - win32_joy_ctx(const win32_joy_ctx&) = delete; win32_joy_ctx& operator=(const win32_joy_ctx&) = delete; -private: - static QString guid_to_string(const GUID guid) - { - char buf[40] = {0}; - wchar_t szGuidW[40] = {0}; - - StringFromGUID2(guid, szGuidW, 40); - WideCharToMultiByte(0, 0, szGuidW, -1, buf, 40, NULL, NULL); - - return QString(buf); - } - static LPDIRECTINPUT8& dinput_handle(); +private: + enum { joylist_refresh_ms = 250 }; - win32_joy_ctx() - { - refresh(true); - } - void release() - { - qDebug() << "release joystick dinput handle"; - joys() = std::unordered_map>(); - { - auto& di = dinput_handle(); - di->Release(); - di = nullptr; - } - } - - void refresh(bool first) - { - if (!first) - { - if (timer_joylist.elapsed_ms() < joylist_refresh_ms) - return; - timer_joylist.start(); - } - - enum_state st(joys(), first); - } QMutex mtx; Timer timer_joylist; - enum { joylist_refresh_ms = 250 }; + + static QString guid_to_string(const GUID guid); + static LPDIRECTINPUT8& dinput_handle(); + win32_joy_ctx(); + void release(); + void refresh(bool first); + + struct joy; + static std::unordered_map>& joys(); struct joy { + enum { first_event_delay_ms = 3000 }; + LPDIRECTINPUTDEVICE8 joy_handle; QString guid, name; bool pressed[128]; Timer first_timer; bool first; - - enum { first_event_delay_ms = 3000 }; - joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name, bool first) : joy_handle(handle), guid(guid), name(name), first(first) + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name, bool first) + : joy_handle(handle), guid(guid), name(name), first(first) { qDebug() << "got joy" << guid; for (int i = 0; i < 128; i++) @@ -201,166 +94,21 @@ private: release(); } - void release() - { - if (joy_handle) - { - (void) joy_handle->Unacquire(); - joy_handle->Release(); - joy_handle = nullptr; - } - } - - bool poll(fn f) - { - HRESULT hr; - bool ok = false; - - if (joy_handle == nullptr) - return false; - - (void) joy_handle->Acquire(); - - if (!FAILED(joy_handle->Poll())) - ok = true; - - if (!ok) - { - qDebug() << "joy acquire failed" << guid << hr; - (void) joy_handle->Unacquire(); - return false; - } - - DIJOYSTATE2 js; - memset(&js, 0, sizeof(js)); - - if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) - { - qDebug() << "joy get state failed" << guid << hr; - return false; - } - - first |= first_timer.elapsed_ms() > first_event_delay_ms; - - for (int i = 0; i < 128; i++) - { - const bool state = !!(js.rgbButtons[i] & 0x80); - if (state != pressed[i] && first) - { - f(guid, i, state); - qDebug() << "btn" << guid << i << state; - } - pressed[i] = state; - } - - return true; - } + void release(); + bool poll(fn f); }; - struct enum_state + class enum_state { std::unordered_map>& joys; - std::vector all; bool first; - - enum_state(std::unordered_map>& joys, bool first) : joys(joys), first(first) - { - HRESULT hr; - LPDIRECTINPUT8 di = dinput_handle(); - - if(FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, - EnumJoysticksCallback, - this, - DIEDFL_ATTACHEDONLY))) - { - qDebug() << "failed enum joysticks" << hr; - return; - } - - for (auto it = joys.begin(); it != joys.end(); ) - { - if (std::find_if(all.cbegin(), all.cend(), [&](const QString& guid2) -> bool { return it->second->guid == guid2; }) == all.cend()) - it = joys.erase(it); - else - it++; - } - } - - static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext) - { - enum_state& state = *reinterpret_cast(pContext); - const QString guid = guid_to_string(pdidInstance->guidInstance); - const QString name = QString(pdidInstance->tszInstanceName); - - auto it = state.joys.find(guid); - const bool exists = it != state.joys.end() && it->second->joy_handle != nullptr; - - state.all.push_back(guid); - - if (!exists) - { - HRESULT hr; - LPDIRECTINPUTDEVICE8 h; - LPDIRECTINPUT8 di = dinput_handle(); - if (FAILED(hr = di->CreateDevice(pdidInstance->guidInstance, &h, nullptr))) - { - qDebug() << "createdevice" << guid << hr; - goto end; - } - if (FAILED(h->SetDataFormat(&c_dfDIJoystick2))) - { - qDebug() << "format"; - h->Release(); - goto end; - } - - if (FAILED(h->SetCooperativeLevel((HWND) GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) - { - qDebug() << "coop"; - h->Release(); - goto end; - } - if (FAILED(hr = h->EnumObjects(EnumObjectsCallback, h, DIDFT_ALL))) - { - qDebug() << "enum-objects"; - h->Release(); - goto end; - } - - qDebug() << "add joy" << guid; - state.joys[guid] = std::make_shared(h, guid, name, state.first); - } - -end: return DIENUM_CONTINUE; - } - - static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx) - { - if (pdidoi->dwType & DIDFT_AXIS) - { - DIPROPRANGE diprg; - memset(&diprg, 0, sizeof(diprg)); - diprg.diph.dwSize = sizeof( DIPROPRANGE ); - diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER ); - diprg.diph.dwHow = DIPH_BYID; - diprg.diph.dwObj = pdidoi->dwType; - diprg.lMax = joy_axis_size; - diprg.lMin = -joy_axis_size; - - HRESULT hr; - - if (FAILED(hr = reinterpret_cast(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph))) - { - qDebug() << "DIPROP_RANGE" << hr; - return DIENUM_STOP; - } - } - - return DIENUM_CONTINUE; - } + + std::vector all; + static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); + static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx); + public: + enum_state(std::unordered_map>& joys, bool first); }; - - static std::unordered_map>& joys(); }; #endif -- cgit v1.2.3 From 22d4c7cc0cadf212052ef72c3bf8ddda6f73a647 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 3 Dec 2015 22:31:57 +0100 Subject: api, compat: clean up verbose fprintf logspam --- opentrack-compat/shm.cpp | 1 - opentrack/keybinding-worker.cpp | 1 - opentrack/win32-joystick.cpp | 1 - 3 files changed, 3 deletions(-) (limited to 'opentrack/keybinding-worker.cpp') diff --git a/opentrack-compat/shm.cpp b/opentrack-compat/shm.cpp index fffb3709..a306d581 100644 --- a/opentrack-compat/shm.cpp +++ b/opentrack-compat/shm.cpp @@ -92,7 +92,6 @@ struct secattr attrs.lpSecurityDescriptor = pSD; attrs.nLength = sizeof(SECURITY_ATTRIBUTES); - fprintf(stderr, "security descriptor ok\n"); fflush(stderr); return; diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 59bc4afd..3c801cf2 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -24,7 +24,6 @@ bool Key::should_process() } KeybindingWorker::~KeybindingWorker() { - qDebug() << "keybinding worker stop"; should_quit = true; wait(); if (dinkeyboard) { diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 0f8a08f8..cd3502b4 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -122,7 +122,6 @@ win32_joy_ctx::win32_joy_ctx() void win32_joy_ctx::release() { - qDebug() << "release joystick dinput handle"; joys() = std::unordered_map>(); { auto& di = dinput_handle(); -- cgit v1.2.3 From 578749c5b7f245aac08c4e514d2767dba059c4db Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 5 Dec 2015 23:30:43 +0100 Subject: api/keys: fix multiple shortcut receivers We can't depend on std::vector's address of array subscript to remain constant, duh. --- opentrack/keybinding-worker.cpp | 15 ++++++++------- opentrack/keybinding-worker.hpp | 20 ++++++++------------ 2 files changed, 16 insertions(+), 19 deletions(-) (limited to 'opentrack/keybinding-worker.cpp') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 3c801cf2..9ff825a0 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -119,7 +119,7 @@ void KeybindingWorker::run() { k.held = held; for (auto& r : receivers) - r(k); + r->operator()(k); }; joy_ctx.poll(f); @@ -147,7 +147,7 @@ void KeybindingWorker::run() { k.keycode = i; for (auto& r : receivers) - r(k); + r->operator()(k); break; } } @@ -160,12 +160,13 @@ void KeybindingWorker::run() { } } -KeybindingWorker::fun* KeybindingWorker::_add_receiver(KeybindingWorker::fun receiver) +KeybindingWorker::fun* KeybindingWorker::_add_receiver(fun& receiver) { QMutexLocker l(&mtx); - receivers.push_back(receiver); - qDebug() << "add receiver" << (long) &receivers[receivers.size()-1]; - return &receivers[receivers.size()-1]; + receivers.push_back(std::unique_ptr(new fun(receiver))); + fun* f = receivers[receivers.size() - 1].get(); + qDebug() << "add receiver" << (long) f; + return f; } void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) @@ -175,7 +176,7 @@ void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) for (int i = receivers.size() - 1; i >= 0; i--) { - if (&receivers[i] == pos) + if (receivers[i].get() == pos) { ok = true; qDebug() << "remove receiver" << (long) pos; diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index 5b669331..c8d8e009 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -47,8 +47,8 @@ private: LPDIRECTINPUTDEVICE8 dinkeyboard; win32_joy_ctx& joy_ctx; volatile bool should_quit; - using fun = std::function; - std::vector receivers; + using fun = std::function; + std::vector> receivers; QMutex mtx; void run() override; @@ -57,27 +57,23 @@ private: KeybindingWorker(const KeybindingWorker&) = delete; KeybindingWorker& operator=(KeybindingWorker&) = delete; static KeybindingWorker& make(); - fun* _add_receiver(fun receiver); + fun* _add_receiver(fun &receiver); void remove_receiver(fun* pos); ~KeybindingWorker(); public: class Token { fun* pos; - //Token(const Token&) = delete; + Token(const Token&) = delete; Token& operator=(Token&) = delete; public: - Token(fun receiver) - { - pos = make()._add_receiver(receiver); - } ~Token() { make().remove_receiver(pos); } + Token(fun receiver) + { + pos = make()._add_receiver(receiver); + } }; - static Token add_receiver(fun receiver) - { - return Token(receiver); - } }; -- cgit v1.2.3 From 0bd32bf56d5b31e7d7e8288b33f536158903e95e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 03:35:33 +0100 Subject: api/keys: nix tautological #ifdef --- opentrack/keybinding-worker.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'opentrack/keybinding-worker.cpp') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 9ff825a0..461f8416 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -105,7 +105,6 @@ void KeybindingWorker::run() { } } -#ifdef _WIN32 { using joy_fn = std::function; @@ -124,7 +123,6 @@ void KeybindingWorker::run() { joy_ctx.poll(f); } -#endif for (int i = 0; i < 256; i++) { -- cgit v1.2.3 From 1aa7bceaed59770adeb389d6c4c8f5561d0e7402 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 05:15:07 +0100 Subject: api/keys: use a fake window for DirectInput handle --- opentrack/keybinding-worker.cpp | 6 ++---- opentrack/keybinding-worker.hpp | 4 +++- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'opentrack/keybinding-worker.cpp') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 461f8416..2ac814af 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -35,9 +35,6 @@ KeybindingWorker::~KeybindingWorker() { } KeybindingWorker::KeybindingWorker() : -#ifdef _WIN32 - joy_ctx(win32_joy_ctx::make()), -#endif should_quit(true) { if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { @@ -58,7 +55,8 @@ KeybindingWorker::KeybindingWorker() : din = 0; return; } - if (dinkeyboard->SetCooperativeLevel(GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { + + if (dinkeyboard->SetCooperativeLevel((HWND) fake_main_window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { dinkeyboard->Release(); din->Release(); din = 0; diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index c8d8e009..fa50a974 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -45,11 +46,12 @@ struct OPENTRACK_EXPORT KeybindingWorker : private QThread private: LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; - win32_joy_ctx& joy_ctx; + win32_joy_ctx joy_ctx; volatile bool should_quit; using fun = std::function; std::vector> receivers; QMutex mtx; + QMainWindow fake_main_window; void run() override; KeybindingWorker(); -- cgit v1.2.3 From d6eb142710e6ac307b4c5c0e0a54166852d71cbc Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 20:14:09 +0100 Subject: api/keys: prevent idempotent keys --- opentrack/keybinding-worker.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'opentrack/keybinding-worker.cpp') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 2ac814af..b0cef22d 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -85,6 +85,7 @@ KeybindingWorker& KeybindingWorker::make() void KeybindingWorker::run() { BYTE keystate[256] = {0}; + BYTE old_keystate[256] = {0}; while (!should_quit) { @@ -125,7 +126,7 @@ void KeybindingWorker::run() { for (int i = 0; i < 256; i++) { Key k; - if (keystate[i] & 0x80) + if (old_keystate[i] != keystate[i] && keystate[i] & 0x80) { switch (i) { @@ -147,6 +148,7 @@ void KeybindingWorker::run() { break; } } + old_keystate[i] = keystate[i]; } } } -- cgit v1.2.3 From 3e543b11f57aa6c010045fb9614eb2638ac6ae81 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 17 Dec 2015 22:52:54 +0100 Subject: api/joy: refresh only manually on certain events Refresh joylist when new listener arrives, and when the joy singleton just gets created. Enumerating joys all the time causes high CPU usage for some of the users. Issue: #279 Backtrace-by: @exulant Reported-by: @aka2k --- opentrack/keybinding-worker.cpp | 1 + opentrack/win32-joystick.cpp | 25 +++++++------------------ opentrack/win32-joystick.hpp | 8 ++------ 3 files changed, 10 insertions(+), 24 deletions(-) (limited to 'opentrack/keybinding-worker.cpp') diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index b0cef22d..39693a7c 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -164,6 +164,7 @@ KeybindingWorker::fun* KeybindingWorker::_add_receiver(fun& receiver) receivers.push_back(std::unique_ptr(new fun(receiver))); fun* f = receivers[receivers.size() - 1].get(); qDebug() << "add receiver" << (long) f; + joy_ctx.refresh(); return f; } diff --git a/opentrack/win32-joystick.cpp b/opentrack/win32-joystick.cpp index 728e2f68..5e6f2011 100644 --- a/opentrack/win32-joystick.cpp +++ b/opentrack/win32-joystick.cpp @@ -6,7 +6,7 @@ void win32_joy_ctx::poll(fn f) { - refresh(false); + //refresh(false); QMutexLocker l(&mtx); @@ -94,7 +94,7 @@ win32_joy_ctx::win32_joy_ctx() qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); assert(!"direct input handle can't be created"); } - refresh(true); + refresh(); } void win32_joy_ctx::release() @@ -104,18 +104,12 @@ void win32_joy_ctx::release() di = nullptr; } -void win32_joy_ctx::refresh(bool first) +void win32_joy_ctx::refresh() { - if (!first) - { - // accessing struct Timer without a lock. worst can happen is seconds - // and nanoseconds getting out of sync. no big deal. - if (timer_joylist.elapsed_ms() < joylist_refresh_ms) - return; - timer_joylist.start(); - } + QMutexLocker l(&mtx); - enum_state st(joys, mtx, fake_main_window, di); + qDebug() << "joy list refresh"; + enum_state st(joys, fake_main_window, di); } QString win32_joy_ctx::guid_to_string(const GUID guid) @@ -184,16 +178,12 @@ bool win32_joy_ctx::joy::poll(fn f) } win32_joy_ctx::enum_state::enum_state(std::unordered_map> &joys, - QMutex& mtx, QMainWindow &fake_main_window, LPDIRECTINPUT8 di) : fake_main_window(fake_main_window), di(di) { - { - QMutexLocker l(&mtx); - this->joys = joys; - } + this->joys = joys; HRESULT hr; @@ -216,7 +206,6 @@ win32_joy_ctx::enum_state::enum_state(std::unordered_mapjoys; } diff --git a/opentrack/win32-joystick.hpp b/opentrack/win32-joystick.hpp index 6d5e1074..9c888326 100644 --- a/opentrack/win32-joystick.hpp +++ b/opentrack/win32-joystick.hpp @@ -57,18 +57,14 @@ struct OPENTRACK_EXPORT win32_joy_ctx win32_joy_ctx(); ~win32_joy_ctx(); - + void refresh(); private: - enum { joylist_refresh_ms = 100 }; - QMutex mtx; - Timer timer_joylist; QMainWindow fake_main_window; LPDIRECTINPUT8 di; static QString guid_to_string(const GUID guid); void release(); - void refresh(bool first); struct joy { @@ -97,7 +93,7 @@ private: static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx); public: - enum_state(std::unordered_map>& joys, QMutex &mtx, QMainWindow& fake_main_window, LPDIRECTINPUT8 di); + enum_state(std::unordered_map>& joys, QMainWindow& fake_main_window, LPDIRECTINPUT8 di); }; }; -- cgit v1.2.3