From 1e9579290745f1d375c4ab8b42f710cb1249bcec Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 1 Nov 2015 11:44:10 +0100 Subject: options-dialog: add missing include --- gui/options-dialog.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'gui/options-dialog.cpp') diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index fef2b0ca..2778be0f 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -10,6 +10,7 @@ #include "keyboard.h" #include #include +#include OptionsDialog::OptionsDialog() { -- 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 'gui/options-dialog.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 'gui/options-dialog.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 e8edf8b4498ff79ae62751cadb9b61ac6569e25d Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 11 Nov 2015 15:29:07 +0100 Subject: options: stringify keyboard mods for joy buttons --- gui/options-dialog.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'gui/options-dialog.cpp') diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 4cff6e77..9631d41e 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -15,7 +15,15 @@ static QString kopts_to_string(const Shortcuts::key_opts& kopts) { if (static_cast(kopts.guid) != "") - return "Joystick button " + QString::number(kopts.button); + { + const int btn = kopts.button & ~Qt::KeyboardModifierMask; + const int mods = kopts.button & Qt::KeyboardModifierMask; + QString mm; + if (mods & Qt::ControlModifier) mm += "Control+"; + if (mods & Qt::AltModifier) mm += "Alt+"; + if (mods & Qt::ShiftModifier) mm += "Shift+"; + return mm + "Joy button " + QString::number(btn); + } if (static_cast(kopts.keycode) == "") return "None"; return kopts.keycode; -- cgit v1.2.3 From 86708a2311c1a3efd975798ff42d934eea0078ed Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 5 Dec 2015 23:32:43 +0100 Subject: api/shortcuts: no longer keep shortcuts hardcoded --- gui/options-dialog.cpp | 3 +++ gui/ui.cpp | 23 +---------------------- gui/ui.h | 4 ---- opentrack/shortcuts.cpp | 48 +++++++++++++++++++++++++++++------------------- opentrack/shortcuts.h | 34 +++++++++++++++++----------------- opentrack/tracker.h | 6 +++--- opentrack/work.hpp | 32 ++++++++++++++++++-------------- 7 files changed, 71 insertions(+), 79 deletions(-) (limited to 'gui/options-dialog.cpp') diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 9631d41e..70d5be62 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -73,6 +73,9 @@ OptionsDialog::OptionsDialog() 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); }); + connect(ui.bind_start, &QPushButton::pressed, [&]() -> void { bind_key(s.start_tracking, ui.start_tracking_text); }); + connect(ui.bind_stop, &QPushButton::pressed, [&]() -> void { bind_key(s.stop_tracking, ui.stop_tracking_text); }); + connect(ui.bind_toggle_tracking, &QPushButton::pressed, [&]() -> void { bind_key(s.toggle_tracking, ui.toggle_tracking_text); }); ui.center_text->setText(kopts_to_string(s.center)); ui.toggle_text->setText(kopts_to_string(s.toggle)); diff --git a/gui/ui.cpp b/gui/ui.cpp index fc6d4754..c3e47912 100644 --- a/gui/ui.cpp +++ b/gui/ui.cpp @@ -281,7 +281,7 @@ void MainWindow::startTracker() { return; } - work = std::make_shared(s, pose, libs, this, winId()); + work = std::make_shared(s, pose, libs, winId()); reload_options(); @@ -489,27 +489,6 @@ void MainWindow::profileSelected(QString name) } } -void MainWindow::shortcutRecentered() -{ - qDebug() << "Center"; - if (work) - work->tracker->center(); -} - -void MainWindow::shortcutToggled() -{ - qDebug() << "Toggle"; - if (work) - work->tracker->toggle_enabled(); -} - -void MainWindow::shortcutZeroed() -{ - qDebug() << "Zero"; - if (work) - work->tracker->zero(); -} - void MainWindow::ensure_tray() { if (tray) diff --git a/gui/ui.h b/gui/ui.h index 44bcde0c..b4bab271 100644 --- a/gui/ui.h +++ b/gui/ui.h @@ -100,10 +100,6 @@ private slots: void startTracker(); void stopTracker(); void reload_options(); -public slots: - void shortcutRecentered(); - void shortcutToggled(); - void shortcutZeroed(); public: MainWindow(); ~MainWindow(); diff --git a/opentrack/shortcuts.cpp b/opentrack/shortcuts.cpp index b961294f..560a31ab 100644 --- a/opentrack/shortcuts.cpp +++ b/opentrack/shortcuts.cpp @@ -9,7 +9,7 @@ #include "shortcuts.h" #include "win32-shortcuts.h" -void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k) +void Shortcuts::bind_keyboard_shortcut(K &key, const key_opts& k) { #if !defined(_WIN32) using sh = QxtGlobalShortcut; @@ -63,33 +63,43 @@ void Shortcuts::bind_keyboard_shortcut(K &key, key_opts& k) #ifdef _WIN32 void Shortcuts::receiver(const Key& k) { - std::vector ks { &keyCenter, &keyToggle, &keyZero }; - for (K* k_ : ks) + const int sz = keys.size(); + for (int i = 0; i < sz; i++) { - if (k.guid != k_->guid) + K& k_ = std::get<0>(keys[i]); + auto& fun = std::get<1>(keys[i]); + if (k.guid != k_.guid) continue; - if (k.keycode != k_->keycode) + if (k.keycode != k_.keycode) continue; if (!k.held) continue; - if (!k_->should_process()) + if (!k_.should_process()) continue; - if (k_->alt && !k.alt) continue; - if (k_->ctrl && !k.ctrl) continue; - if (k_->shift && !k.shift) continue; + if (k_.alt && !k.alt) continue; + if (k_.ctrl && !k.ctrl) continue; + if (k_.shift && !k.shift) continue; - if (k_ == &keyCenter) - emit center(); - else if (k_ == &keyToggle) - emit toggle(); - else if (k_ == &keyZero) - emit zero(); + fun(); } } #endif -void Shortcuts::reload() { - bind_keyboard_shortcut(keyCenter, s.center); - bind_keyboard_shortcut(keyToggle, s.toggle); - bind_keyboard_shortcut(keyZero, s.zero); +void Shortcuts::reload(const std::vector > &keys_) +{ + const int sz = keys_.size(); + keys = std::vector(); + + for (int i = 0; i < sz; i++) + { + const auto& kk = keys_[i]; + const key_opts& opts = std::get<0>(kk); + auto& fun = std::get<1>(kk); + K k; + bind_keyboard_shortcut(k, opts); + keys.push_back(std::tuple(k, fun)); +#ifndef _WIN32 + connect(k.get(), &QGlobalShortcut::activated, fun); +#endif + } } diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index 8acc5ba5..4dec7c2c 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -8,6 +8,9 @@ #pragma once #include +#include +#include +#include #ifdef BUILD_api # include "opentrack-compat/export.hpp" @@ -36,10 +39,10 @@ public: Key #endif ; - - K keyCenter; - K keyToggle; - K keyZero; + + using fun = std::function; + using tt = std::tuple; + std::vector keys; #ifdef _WIN32 KeybindingWorker::Token key_token; #endif @@ -56,32 +59,29 @@ public: }; struct settings : opts { - key_opts center, toggle, zero; + key_opts center, toggle, zero, start_tracking, stop_tracking, toggle_tracking; main_settings s_main; settings() : opts("keyboard-shortcuts"), center(b, "center"), toggle(b, "toggle"), - zero(b, "zero") + zero(b, "zero"), + start_tracking(b, "start-tracking"), + stop_tracking(b, "stop-tracking"), + toggle_tracking(b, "toggle-tracking") {} } s; - Shortcuts() + Shortcuts() : #ifdef _WIN32 - : key_token(KeybindingWorker::add_receiver([&](const Key& k) { receiver(k); })) + key_token([&](const Key& k) { receiver(k); }) #endif - { - reload(); - } + {} - void reload(); + void reload(const std::vector > &keys); private: - void bind_keyboard_shortcut(K &key, key_opts& k); + void bind_keyboard_shortcut(K &key, const key_opts& k); #ifdef _WIN32 void receiver(const Key& k); #endif -signals: - void center(); - void toggle(); - void zero(); }; diff --git a/opentrack/tracker.h b/opentrack/tracker.h index e26c3f7a..36b5cad4 100644 --- a/opentrack/tracker.h +++ b/opentrack/tracker.h @@ -80,7 +80,7 @@ public: void get_raw_and_mapped_poses(double* mapped, double* raw) const; void start() { QThread::start(); } - void toggle_enabled() { enabledp = !enabledp; } - void center() { centerp = !centerp; } - void zero() { zero_ = !zero_; } + void toggle_enabled() { qDebug() << "toggle enabled"; enabledp = !enabledp; } + void center() { qDebug() << "toggle center"; centerp = !centerp; } + void zero() { qDebug() << "toggle zero"; zero_ = !zero_; } }; diff --git a/opentrack/work.hpp b/opentrack/work.hpp index e338e9f4..a3c0e014 100644 --- a/opentrack/work.hpp +++ b/opentrack/work.hpp @@ -16,6 +16,9 @@ #include #include #include +#include +#include +#include struct Work { @@ -24,28 +27,29 @@ struct Work mem tracker; mem sc; WId handle; - - Work(main_settings& s, Mappings& m, SelectedLibraries& libs, QObject* recv, WId handle) : + using fn = std::function; + using key_opts = Shortcuts::key_opts; + using tt = std::tuple; + std::vector> keys; + + Work(main_settings& s, Mappings& m, SelectedLibraries& libs, WId handle) : s(s), libs(libs), tracker(std::make_shared(s, m, libs)), sc(std::make_shared()), - handle(handle) + handle(handle), + keys { + tt(sc->s.center, [&]() -> void { tracker->center(); }), + tt(sc->s.toggle, [&]() -> void { tracker->toggle_enabled(); }), + tt(sc->s.zero, [&]() -> void { tracker->zero(); }), + } { -#ifndef _WIN32 - QObject::connect(sc->keyCenter.get(), SIGNAL(activated()), recv, SLOT(shortcutRecentered())); - QObject::connect(sc->keyToggle.get(), SIGNAL(activated()), recv, SLOT(shortcutToggled())); - QObject::connect(sc->keyZero.get(), SIGNAL(activated()), recv, SLOT(shortcutZeroed())); -#else - QObject::connect(sc.get(), SIGNAL(center()), recv, SLOT(shortcutRecentered())); - QObject::connect(sc.get(), SIGNAL(toggle()), recv, SLOT(shortcutToggled())); - QObject::connect(sc.get(), SIGNAL(zero()), recv, SLOT(shortcutZeroed())); -#endif - tracker->start(); + reload_shortcuts(); + tracker->start(); } void reload_shortcuts() { - sc->reload(); + sc->reload(keys); } ~Work() -- cgit v1.2.3 From 52b75a02aeeaf2c23f5af32fededf4e5fb24bade Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 00:43:58 +0100 Subject: api, main: implement global shortcuts for controlling tracking Issue: #252 That involves moving stuff around to get rid of circular dependencies. You need to bind keys to shortcuts again this once. --- gui/options-dialog.cpp | 100 +++++++++++++++++++++++--------------------- gui/options-dialog.hpp | 12 +++--- gui/ui.cpp | 50 +++++++++++++++++++--- gui/ui.h | 10 +++++ opentrack/main-settings.hpp | 26 ++++++++++-- opentrack/shortcuts.h | 27 +----------- opentrack/work.hpp | 7 ++-- 7 files changed, 140 insertions(+), 92 deletions(-) (limited to 'gui/options-dialog.cpp') diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 70d5be62..1edf069d 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -12,7 +12,7 @@ #include #include -static QString kopts_to_string(const Shortcuts::key_opts& kopts) +static QString kopts_to_string(const key_opts& kopts) { if (static_cast(kopts.guid) != "") { @@ -29,60 +29,65 @@ static QString kopts_to_string(const Shortcuts::key_opts& kopts) return kopts.keycode; } -OptionsDialog::OptionsDialog() +OptionsDialog::OptionsDialog(main_settings& main, std::function register_global_keys) + : main(main), register_global_keys(register_global_keys) { ui.setupUi(this); connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); - tie_setting(s.s_main.tray_enabled, ui.trayp); + tie_setting(main.tray_enabled, ui.trayp); - tie_setting(s.s_main.center_at_startup, ui.center_at_startup); + tie_setting(main.center_at_startup, ui.center_at_startup); - tie_setting(s.s_main.tcomp_p, ui.tcomp_enable); - tie_setting(s.s_main.tcomp_tz, ui.tcomp_rz); - - tie_setting(s.s_main.a_x.zero, ui.pos_tx); - tie_setting(s.s_main.a_y.zero, ui.pos_ty); - tie_setting(s.s_main.a_z.zero, ui.pos_tz); - tie_setting(s.s_main.a_yaw.zero, ui.pos_rx); - tie_setting(s.s_main.a_pitch.zero, ui.pos_ry); - tie_setting(s.s_main.a_roll.zero, ui.pos_rz); - - tie_setting(s.s_main.a_yaw.invert, ui.invert_yaw); - tie_setting(s.s_main.a_pitch.invert, ui.invert_pitch); - tie_setting(s.s_main.a_roll.invert, ui.invert_roll); - tie_setting(s.s_main.a_x.invert, ui.invert_x); - tie_setting(s.s_main.a_y.invert, ui.invert_y); - tie_setting(s.s_main.a_z.invert, ui.invert_z); - - tie_setting(s.s_main.a_yaw.src, ui.src_yaw); - tie_setting(s.s_main.a_pitch.src, ui.src_pitch); - tie_setting(s.s_main.a_roll.src, ui.src_roll); - tie_setting(s.s_main.a_x.src, ui.src_x); - tie_setting(s.s_main.a_y.src, ui.src_y); - tie_setting(s.s_main.a_z.src, ui.src_z); + tie_setting(main.tcomp_p, ui.tcomp_enable); + tie_setting(main.tcomp_tz, ui.tcomp_rz); + + tie_setting(main.a_x.zero, ui.pos_tx); + tie_setting(main.a_y.zero, ui.pos_ty); + tie_setting(main.a_z.zero, ui.pos_tz); + tie_setting(main.a_yaw.zero, ui.pos_rx); + tie_setting(main.a_pitch.zero, ui.pos_ry); + tie_setting(main.a_roll.zero, ui.pos_rz); + + tie_setting(main.a_yaw.invert, ui.invert_yaw); + tie_setting(main.a_pitch.invert, ui.invert_pitch); + tie_setting(main.a_roll.invert, ui.invert_roll); + tie_setting(main.a_x.invert, ui.invert_x); + tie_setting(main.a_y.invert, ui.invert_y); + tie_setting(main.a_z.invert, ui.invert_z); + + tie_setting(main.a_yaw.src, ui.src_yaw); + tie_setting(main.a_pitch.src, ui.src_pitch); + tie_setting(main.a_roll.src, ui.src_roll); + tie_setting(main.a_x.src, ui.src_x); + tie_setting(main.a_y.src, ui.src_y); + tie_setting(main.a_z.src, ui.src_z); - tie_setting(s.s_main.camera_yaw, ui.camera_yaw); - tie_setting(s.s_main.camera_pitch, ui.camera_pitch); - tie_setting(s.s_main.camera_roll, ui.camera_roll); - - tie_setting(s.s_main.center_method, ui.center_method); - - 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); }); - connect(ui.bind_start, &QPushButton::pressed, [&]() -> void { bind_key(s.start_tracking, ui.start_tracking_text); }); - connect(ui.bind_stop, &QPushButton::pressed, [&]() -> void { bind_key(s.stop_tracking, ui.stop_tracking_text); }); - connect(ui.bind_toggle_tracking, &QPushButton::pressed, [&]() -> void { bind_key(s.toggle_tracking, ui.toggle_tracking_text); }); - - 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)); + tie_setting(main.camera_yaw, ui.camera_yaw); + tie_setting(main.camera_pitch, ui.camera_pitch); + tie_setting(main.camera_roll, ui.camera_roll); + + tie_setting(main.center_method, ui.center_method); + + connect(ui.bind_center, &QPushButton::pressed, [&]() -> void { bind_key(main.key_center, ui.center_text); }); + connect(ui.bind_zero, &QPushButton::pressed, [&]() -> void { bind_key(main.key_zero, ui.zero_text); }); + connect(ui.bind_toggle, &QPushButton::pressed, [&]() -> void { bind_key(main.key_toggle, ui.toggle_text); }); + connect(ui.bind_start, &QPushButton::pressed, [&]() -> void { bind_key(main.key_start_tracking, ui.start_tracking_text); }); + connect(ui.bind_stop, &QPushButton::pressed, [&]() -> void { bind_key(main.key_stop_tracking, ui.stop_tracking_text); }); + connect(ui.bind_toggle_tracking, &QPushButton::pressed, [&]() -> void { bind_key(main.key_toggle_tracking, ui.toggle_tracking_text); }); + + ui.center_text->setText(kopts_to_string(main.key_center)); + ui.toggle_text->setText(kopts_to_string(main.key_toggle)); + ui.zero_text->setText(kopts_to_string(main.key_zero)); + + ui.start_tracking_text->setText(kopts_to_string(main.key_start_tracking)); + ui.stop_tracking_text->setText(kopts_to_string(main.key_stop_tracking)); + ui.toggle_tracking_text->setText(kopts_to_string(main.key_toggle_tracking)); } -void OptionsDialog::bind_key(Shortcuts::key_opts& kopts, QLabel* label) +void OptionsDialog::bind_key(key_opts& kopts, QLabel* label) { kopts.button = -1; kopts.guid = ""; @@ -111,22 +116,21 @@ void OptionsDialog::bind_key(Shortcuts::key_opts& kopts, QLabel* label) } }); d.exec(); + register_global_keys(); label->setText(kopts_to_string(kopts)); delete k; delete l; } void OptionsDialog::doOK() { - s.b->save(); - s.s_main.b->save(); + main.b->save(); ui.game_detector->save(); this->close(); emit reload(); } void OptionsDialog::doCancel() { - s.b->reload(); - s.s_main.b->reload(); + main.b->reload(); ui.game_detector->revert(); close(); } diff --git a/gui/options-dialog.hpp b/gui/options-dialog.hpp index 308b5b0f..72ae3c30 100644 --- a/gui/options-dialog.hpp +++ b/gui/options-dialog.hpp @@ -1,9 +1,10 @@ #pragma once -#include -#include #include "ui_settings.h" #include "opentrack/shortcuts.h" +#include +#include +#include class OptionsDialog: public QWidget { @@ -11,13 +12,14 @@ class OptionsDialog: public QWidget signals: void reload(); public: - OptionsDialog(); + OptionsDialog(main_settings& main, std::function register_global_keys); private: + main_settings& main; + std::function register_global_keys; Ui::UI_Settings ui; - Shortcuts::settings s; void closeEvent(QCloseEvent *) override { doCancel(); } private slots: void doOK(); void doCancel(); - void bind_key(Shortcuts::key_opts &kopts, QLabel* label); + void bind_key(key_opts &kopts, QLabel* label); }; diff --git a/gui/ui.cpp b/gui/ui.cpp index c3e47912..26fcd9ed 100644 --- a/gui/ui.cpp +++ b/gui/ui.cpp @@ -108,10 +108,40 @@ MainWindow::MainWindow() : "Configuration not saved.", "Can't create configuration directory! Expect major malfunction.", QMessageBox::Ok, QMessageBox::NoButton); - + + connect(this, &MainWindow::emit_start_tracker, + this, [&]() -> void { qDebug() << "start tracker"; startTracker(); }, + Qt::QueuedConnection); + + connect(this, &MainWindow::emit_stop_tracker, + this, [&]() -> void { qDebug() << "stop tracker"; stopTracker(); }, + Qt::QueuedConnection); + + connect(this, &MainWindow::emit_toggle_tracker, + this, [&]() -> void { qDebug() << "toggle tracker"; if (work) stopTracker(); else startTracker(); }, + Qt::QueuedConnection); + + register_shortcuts(); + ui.btnStartTracker->setFocus(); } +void MainWindow::register_shortcuts() +{ + using t_shortcut = std::tuple; + + std::vector keys { + t_shortcut(s.key_start_tracking, [&]() -> void { emit_start_tracker(); }), + t_shortcut(s.key_stop_tracking, [&]() -> void { emit_stop_tracker(); }), + t_shortcut(s.key_toggle_tracking, [&]() -> void { emit_toggle_tracker(); }), + }; + + global_shortcuts.reload(keys); + + if (work) + work->reload_shortcuts(); +} + bool MainWindow::get_new_config_name_from_dialog(QString& ret) { new_file_dialog dlg; @@ -261,6 +291,9 @@ void MainWindow::reload_options() } void MainWindow::startTracker() { + if (work) + return; + // tracker dtor needs run first work = nullptr; @@ -306,7 +339,10 @@ void MainWindow::startTracker() { ui.btnStopTracker->setFocus(); } -void MainWindow::stopTracker( ) { +void MainWindow::stopTracker() { + if (!work) + return; + //ui.game_name->setText("Not connected"); pose_update_timer.stop(); @@ -436,7 +472,7 @@ void MainWindow::showFilterSettings() { } template -bool mk_window(mem* place, Args... params) +bool mk_window(mem* place, Args&&... params) { if (*place && (*place)->isVisible()) { @@ -446,7 +482,7 @@ bool mk_window(mem* place, Args... params) } else { - *place = std::make_shared(params...); + *place = std::make_shared(std::forward(params)...); (*place)->setWindowFlags(Qt::Dialog); (*place)->show(); (*place)->raise(); @@ -455,12 +491,14 @@ bool mk_window(mem* place, Args... params) } void MainWindow::show_options_dialog() { - if (mk_window(&options_widget)) + if (mk_window(&options_widget, + s, + [&]() -> void { register_shortcuts(); })) connect(options_widget.get(), SIGNAL(reload()), this, SLOT(reload_options())); } void MainWindow::showCurveConfiguration() { - mk_window(&mapping_widget, pose, s); + mk_window(&mapping_widget, pose, s); } void MainWindow::exit() { diff --git a/gui/ui.h b/gui/ui.h index b4bab271..12ef1f24 100644 --- a/gui/ui.h +++ b/gui/ui.h @@ -17,6 +17,9 @@ #include #include +#include +#include + #include "ui_main.h" #include "opentrack-compat/options.hpp" @@ -35,6 +38,8 @@ using namespace options; class MainWindow : public QMainWindow, private State { Q_OBJECT + + Shortcuts global_shortcuts; Ui::OpentrackUI ui; mem tray; @@ -76,6 +81,7 @@ class MainWindow : public QMainWindow, private State static bool get_new_config_name_from_dialog(QString &ret); void set_profile(const QString& profile); void maybe_save(); + void register_shortcuts(); private slots: void _save(); void save(); @@ -100,6 +106,10 @@ private slots: void startTracker(); void stopTracker(); void reload_options(); +signals: + void emit_start_tracker(); + void emit_stop_tracker(); + void emit_toggle_tracker(); public: MainWindow(); ~MainWindow(); diff --git a/opentrack/main-settings.hpp b/opentrack/main-settings.hpp index b7b086ad..793c52f7 100644 --- a/opentrack/main-settings.hpp +++ b/opentrack/main-settings.hpp @@ -32,7 +32,18 @@ private: } }; -struct main_settings : opts { +struct key_opts { + value keycode, guid; + value button; + + key_opts(pbundle b, const QString& name) : + keycode(b, QString("keycode-%1").arg(name), ""), + guid(b, QString("guid-%1").arg(name), ""), + button(b, QString("button-%1").arg(name), -1) + {} +}; + +struct main_settings : opts { value tracker_dll, filter_dll, protocol_dll; axis_opts a_x, a_y, a_z, a_yaw, a_pitch, a_roll; value tcomp_p, tcomp_tz; @@ -40,6 +51,8 @@ struct main_settings : opts { value camera_yaw, camera_pitch, camera_roll; value center_at_startup; value center_method; + key_opts key_start_tracking, key_stop_tracking, key_toggle_tracking; + key_opts key_center, key_toggle, key_zero; main_settings() : opts("opentrack-ui"), tracker_dll(b, "tracker-dll", ""), @@ -58,6 +71,13 @@ struct main_settings : opts { camera_pitch(b, "camera-pitch", 0), camera_roll(b, "camera-roll", 0), center_at_startup(b, "center-at-startup", true), - center_method(b, "centering-method", true) - {} + center_method(b, "centering-method", true), + key_start_tracking(b, "start-tracking"), + key_stop_tracking(b, "stop-tracking"), + key_toggle_tracking(b, "toggle-tracking"), + key_center(b, "center"), + key_toggle(b, "toggle"), + key_zero(b, "zero") + { + } }; diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index 4dec7c2c..f8343ad8 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -46,31 +46,6 @@ public: #ifdef _WIN32 KeybindingWorker::Token key_token; #endif - - struct key_opts { - value keycode, guid; - value button; - - key_opts(pbundle b, const QString& name) : - keycode(b, QString("keycode-%1").arg(name), ""), - guid(b, QString("guid-%1").arg(name), ""), - button(b, QString("button-%1").arg(name), -1) - {} - }; - - struct settings : opts { - key_opts center, toggle, zero, start_tracking, stop_tracking, toggle_tracking; - main_settings s_main; - settings() : - opts("keyboard-shortcuts"), - center(b, "center"), - toggle(b, "toggle"), - zero(b, "zero"), - start_tracking(b, "start-tracking"), - stop_tracking(b, "stop-tracking"), - toggle_tracking(b, "toggle-tracking") - {} - } s; Shortcuts() : #ifdef _WIN32 @@ -78,7 +53,7 @@ public: #endif {} - void reload(const std::vector > &keys); + void reload(const std::vector > &keys); private: void bind_keyboard_shortcut(K &key, const key_opts& k); #ifdef _WIN32 diff --git a/opentrack/work.hpp b/opentrack/work.hpp index a3c0e014..4188b937 100644 --- a/opentrack/work.hpp +++ b/opentrack/work.hpp @@ -28,7 +28,6 @@ struct Work mem sc; WId handle; using fn = std::function; - using key_opts = Shortcuts::key_opts; using tt = std::tuple; std::vector> keys; @@ -38,9 +37,9 @@ struct Work sc(std::make_shared()), handle(handle), keys { - tt(sc->s.center, [&]() -> void { tracker->center(); }), - tt(sc->s.toggle, [&]() -> void { tracker->toggle_enabled(); }), - tt(sc->s.zero, [&]() -> void { tracker->zero(); }), + tt(s.key_center, [&]() -> void { tracker->center(); }), + tt(s.key_toggle, [&]() -> void { tracker->toggle_enabled(); }), + tt(s.key_zero, [&]() -> void { tracker->zero(); }), } { reload_shortcuts(); -- cgit v1.2.3 From 4e74d6edef94e4f2f7caae76088f91e9ee993fba Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 05:14:07 +0100 Subject: gui/keys: allow for pausing global keystrokes for options dialog Toggling tracking while prompting for toggle tracking key causes a deadlock somewhere. --- gui/options-dialog.cpp | 10 ++++++++-- gui/options-dialog.hpp | 3 ++- gui/ui.cpp | 12 +++++++----- gui/ui.h | 1 + 4 files changed, 18 insertions(+), 8 deletions(-) (limited to 'gui/options-dialog.cpp') diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 1edf069d..65407184 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -29,8 +29,12 @@ static QString kopts_to_string(const key_opts& kopts) return kopts.keycode; } -OptionsDialog::OptionsDialog(main_settings& main, std::function register_global_keys) - : main(main), register_global_keys(register_global_keys) +OptionsDialog::OptionsDialog(main_settings& main, + std::function register_global_keys, + std::function pause_keybindings) : + main(main), + register_global_keys(register_global_keys), + pause_keybindings(pause_keybindings) { ui.setupUi(this); @@ -115,7 +119,9 @@ void OptionsDialog::bind_key(key_opts& kopts, QLabel* label) d.close(); } }); + pause_keybindings(true); d.exec(); + pause_keybindings(false); register_global_keys(); label->setText(kopts_to_string(kopts)); delete k; diff --git a/gui/options-dialog.hpp b/gui/options-dialog.hpp index 72ae3c30..7700162b 100644 --- a/gui/options-dialog.hpp +++ b/gui/options-dialog.hpp @@ -12,10 +12,11 @@ class OptionsDialog: public QWidget signals: void reload(); public: - OptionsDialog(main_settings& main, std::function register_global_keys); + OptionsDialog(main_settings& main, std::function register_global_keys, std::function pause_keybindings); private: main_settings& main; std::function register_global_keys; + std::function pause_keybindings; Ui::UI_Settings ui; void closeEvent(QCloseEvent *) override { doCancel(); } private slots: diff --git a/gui/ui.cpp b/gui/ui.cpp index 26fcd9ed..e59b1c23 100644 --- a/gui/ui.cpp +++ b/gui/ui.cpp @@ -23,7 +23,8 @@ MainWindow::MainWindow() : pose_update_timer(this), kbd_quit(QKeySequence("Ctrl+Q"), this), no_feed_pixmap(":/images/no-feed.png"), - is_refreshing_profiles(false) + is_refreshing_profiles(false), + keys_paused(false) { ui.setupUi(this); @@ -110,15 +111,15 @@ MainWindow::MainWindow() : QMessageBox::Ok, QMessageBox::NoButton); connect(this, &MainWindow::emit_start_tracker, - this, [&]() -> void { qDebug() << "start tracker"; startTracker(); }, + this, [&]() -> void { if (keys_paused) return; qDebug() << "start tracker"; startTracker(); }, Qt::QueuedConnection); connect(this, &MainWindow::emit_stop_tracker, - this, [&]() -> void { qDebug() << "stop tracker"; stopTracker(); }, + this, [&]() -> void { if (keys_paused) return; qDebug() << "stop tracker"; stopTracker(); }, Qt::QueuedConnection); connect(this, &MainWindow::emit_toggle_tracker, - this, [&]() -> void { qDebug() << "toggle tracker"; if (work) stopTracker(); else startTracker(); }, + this, [&]() -> void { if (keys_paused) return; qDebug() << "toggle tracker"; if (work) stopTracker(); else startTracker(); }, Qt::QueuedConnection); register_shortcuts(); @@ -493,7 +494,8 @@ bool mk_window(mem* place, Args&&... params) void MainWindow::show_options_dialog() { if (mk_window(&options_widget, s, - [&]() -> void { register_shortcuts(); })) + [&]() -> void { register_shortcuts(); }, + [&](bool flag) -> void { keys_paused = flag; })) connect(options_widget.get(), SIGNAL(reload()), this, SLOT(reload_options())); } diff --git a/gui/ui.h b/gui/ui.h index 12ef1f24..ee0a3ce7 100644 --- a/gui/ui.h +++ b/gui/ui.h @@ -56,6 +56,7 @@ class MainWindow : public QMainWindow, private State process_detector_worker det; QMenu profile_menu; bool is_refreshing_profiles; + volatile bool keys_paused; QTimer save_timer; mem current_tracker() -- cgit v1.2.3 From 2de0b6427d8d768771cf22686c1c3b65f15e2f40 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 06:15:19 +0100 Subject: gui/settings: don't forget to show a modal dialog before executing --- gui/options-dialog.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'gui/options-dialog.cpp') diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 65407184..a7efdb75 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -99,18 +99,18 @@ void OptionsDialog::bind_key(key_opts& kopts, QLabel* label) QDialog d; auto l = new QHBoxLayout; l->setMargin(0); - auto k = new KeyboardListener; - l->addWidget(k); + KeyboardListener k; + l->addWidget(&k); d.setLayout(l); d.setFixedSize(QSize(500, 300)); d.setWindowFlags(Qt::Dialog); - connect(k, &KeyboardListener::key_pressed, [&] (QKeySequence s) -> void { + 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, bool held) -> void { + connect(&k, &KeyboardListener::joystick_button_pressed, [&](QString guid, int idx, bool held) -> void { if (!held) { kopts.guid = guid; @@ -120,11 +120,11 @@ void OptionsDialog::bind_key(key_opts& kopts, QLabel* label) } }); pause_keybindings(true); + d.show(); d.exec(); pause_keybindings(false); register_global_keys(); label->setText(kopts_to_string(kopts)); - delete k; delete l; } -- cgit v1.2.3 From da8ec5c60841a926874c9ef2c4fed0078d47ebc8 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 6 Dec 2015 06:20:56 +0100 Subject: gui/settings: set parent, otherwise not modal --- gui/options-dialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gui/options-dialog.cpp') diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index a7efdb75..e1324ccc 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -96,7 +96,7 @@ void OptionsDialog::bind_key(key_opts& kopts, QLabel* label) kopts.button = -1; kopts.guid = ""; kopts.keycode = ""; - QDialog d; + QDialog d(this); auto l = new QHBoxLayout; l->setMargin(0); KeyboardListener k; @@ -104,6 +104,7 @@ void OptionsDialog::bind_key(key_opts& kopts, QLabel* label) d.setLayout(l); d.setFixedSize(QSize(500, 300)); d.setWindowFlags(Qt::Dialog); + d.setWindowModality(Qt::ApplicationModal); connect(&k, &KeyboardListener::key_pressed, [&] (QKeySequence s) -> void { kopts.keycode = s.toString(QKeySequence::PortableText); kopts.guid = ""; -- cgit v1.2.3